Tengo una función simplificada que se ve así:
function(query) {
myApi.exec('SomeCommand', function(response) {
return response;
});
}
Básicamente, quiero que llame myApi.exec
y devuelva la respuesta que se da en la devolución de llamada lambda. Sin embargo, el código anterior no funciona y simplemente regresa de inmediato.
Solo por un intento muy hostil, probé lo siguiente, que no funcionó, pero al menos te haces una idea de lo que estoy tratando de lograr:
function(query) {
var r;
myApi.exec('SomeCommand', function(response) {
r = response;
});
while (!r) {}
return r;
}
Básicamente, ¿cuál es una buena forma de 'nodo.js / evento impulsado' de hacer esto? Quiero que mi función espere hasta que se llame la devolución de llamada y luego devuelva el valor que se le pasó.
Respuestas:
La forma de "hacer un buen nodo.js / evento" es no esperar .
Como casi todo lo demás cuando se trabaja con sistemas controlados por eventos como el nodo, su función debe aceptar un parámetro de devolución de llamada que se invocará cuando se complete el cálculo. La persona que llama no debe esperar a que el valor sea "devuelto" en el sentido normal, sino que debe enviar la rutina que manejará el valor resultante:
Entonces no lo usas así:
Pero así:
fuente
fs
sync*
métodos). Como tal, creo que esta sigue siendo una pregunta válida. ¿Hay una buena manera de lograr el bloqueo en el nodo aparte de la espera ocupada?sync
que hacen los métodos. (2) Use fibras, github.com/laverdet/node-fibers , (3) Use promesas, por ejemplo, la biblioteca Q, (4) Use una capa delgada en la parte superior de javascript, que parece bloqueante, pero se compila de forma asíncrona, like maxtaco.github.com/coffee-scriptUna forma de lograr esto es envolver la llamada API en una promesa y luego usarla
await
para esperar el resultado.Salida:
fuente
async/await
A menudo no lo necesito, así que tenga problemas para recordar cómo manejar esta situación, estoy copiando esto para mis notas / referencias personales.mira esto: https://github.com/luciotato/waitfor-ES6
su código con wait.for: (requiere generadores, --harmony flag)
fuente
Si no desea utilizar la devolución de llamada, puede utilizar el módulo "Q".
Por ejemplo:
Para obtener más información, consulte esto: https://github.com/kriskowal/q
fuente
Si desea que sea muy simple y fácil, sin bibliotecas sofisticadas, esperar a que las funciones de devolución de llamada se ejecuten en el nodo, antes de ejecutar otro código, es así:
fuente
Nota: Esta respuesta probablemente no debería usarse en el código de producción. Es un truco y debes saber sobre las implicaciones.
Existe el módulo uvrun (actualizado para las versiones más recientes de Nodejs aquí ) donde puede ejecutar una ronda de bucle único del bucle de evento principal de libuv (que es el bucle principal de Nodejs).
Su código se vería así:
(Puede utilizarlo de forma alternativa
uvrun.runNoWait()
. Eso podría evitar algunos problemas con el bloqueo, pero requiere un 100% de CPU).Tenga en cuenta que este enfoque invalida el propósito de Nodejs, es decir, tener todo asíncrono y sin bloqueo. Además, podría aumentar mucho la profundidad de su pila de llamadas, por lo que podría terminar con desbordamientos de pila. Si ejecuta dicha función de forma recursiva, definitivamente tendrá problemas.
Vea las otras respuestas sobre cómo rediseñar su código para hacerlo "bien".
Esta solución aquí probablemente solo sea útil cuando realice pruebas y esp. desea tener un código sincronizado y en serie.
fuente
Desde el nodo 4.8.0 puede usar la función de ES6 llamada generador. Puede seguir este artículo para conceptos más profundos. Pero básicamente puedes usar generadores y promesas para hacer este trabajo. Estoy usando bluebird para promisificar y administrar el generador.
Su código debería estar bien como en el ejemplo a continuación.
fuente
suponiendo que tenga una función:
puede utilizar devoluciones de llamada como esta:
fuente
Eso anula el propósito de no bloquear IO: lo está bloqueando cuando no necesita bloqueo
:)
Debe anidar sus devoluciones de llamada en lugar de obligar a node.js a esperar, o llamar a otra devolución de llamada dentro de la devolución de llamada donde necesita el resultado
r
.Lo más probable es que, si necesita forzar el bloqueo, esté pensando en que su arquitectura es incorrecta.
fuente
http.get()
alguna URL yconsole.log()
su contenido. ¿Por qué tengo que saltar hacia atrás para hacer eso en Node?Usar async y esperar es mucho más fácil.
fuente