javascript - tutorial - js to coff
Exportar módulo de nodo desde el resultado de la promesa (2)
Los módulos Node.js se cargan sincrónicamente .
Puede lidiar con esto exportando el valor Promesa.
#@ your module.js
module.exports = new Promise()
y:
#@ your app.js
const mod = require(''./module'');
mod.then((value => ...);
Estoy tratando de reescribir un módulo para devolver un valor diferente al anterior, pero ahora usa una llamada asincrónica para obtener ese valor.
(con
child_process
si es importante).
Lo he envuelto en una promesa, pero eso no es crítico para mí: puede estar en la devolución de llamada original de child_process, pero el problema es que no puedo encadenar la promesa en todas partes de la aplicación porque necesito que esto se sincronice.
Aquí está mi módulo:
exec = require(''child_process'').exec
platformHome = process.env[if process.platform is ''win32'' then ''USERPROFILE'' else ''HOME'']
getExecPath = new Promise (resolve, reject) ->
path = process.env.GEM_HOME
if path
resolve(path)
else
exec ''gem environment'', (err, stdout, stderr) ->
unless err
line = stdout.split(//r?/n/)
.find((l) -> ~l.indexOf(''EXECUTABLE DIRECTORY''))
if line
resolve line[line.indexOf('': '') + 2..]
else
reject undefined
GEM_HOME = undefined
getExecPath.then (path) ->
GEM_HOME = path
.catch ->
GEM_HOME = "#{platformHome}/.gem/ruby/2.3.0"
.then =>
module.exports = GEM_HOME // or simply return it
Claramente, cuando requiero el módulo, esto no funciona, y si devuelvo la promesa en sí y lo uso después de
require
, mi próximo
module.exports
. Las
module.exports
serán asíncronas, y esta cadena continuará.
¿Cómo evito este patrón?
Los módulos en el nodo que cargue con
require()
se cargan sincrónicamente y no es posible que
require
devuelva ningún valor que se cargue asincrónicamente.
Puede devolver una promesa, pero los usuarios de ese módulo tendrían que usarlo como:
require(''module-name'').then(value => {
// you have your value here
});
No sería posible escribir:
var value = require(''module-name'');
// you cannot have your value here because this line
// will get evaluated before that value is available
Por supuesto, puede tener la promesa resuelta dentro de su módulo y hacer que establezca una propiedad en el objeto exportado agregando algo como esto:
module.exports = { GEM_HOME: null };
y cambiando:
module.exports = GEM_HOME
a:
module.exports.GEM_HOME = GEM_HOME
En ese caso, cualquier otro módulo que use este módulo como:
var x = require(''module-name'');
tendrá
x.GEM_HOME
originalmente establecido en
null
pero eventualmente se cambiará a un valor correcto algún tiempo después.
Sin embargo, no estaría disponible de inmediato, ya que
require()
devuelve antes de que se cumpla la promesa y se establezca el valor.
Hay una discusión en curso para introducir la carga de módulos asíncronos con diferentes sintaxis y semánticas que pueden ser adecuadas para su caso de uso. Es un tema controvertido y vale la pena leer toda la justificación detrás de esto: ver:
- Node.js, TC-39 y módulos de James M Snell de iBM
- Interoperabilidad del módulo ES6 : propuestas de mejora de Node.js
- En defensa de .js : una propuesta para los módulos Node.js de Dave Herman, Yehuda Katz y Caridy Patiño
- Discusión sobre la solicitud de extracción # 3 de node-eps (002: interoperabilidad del módulo ES6)
Vea también esta respuesta para más detalles: