javascript - studio - Nodo JS UnhandledPromiseRejectionWarning
node js foundation (7)
Entonces, estoy probando un componente que se basa en un emisor de eventos. Para hacerlo, se me ocurrió una solución usando Promesas con Mocha + Chai:
it(''should transition with the correct event'', (done) => {
const cFSM = new CharacterFSM({}, emitter, transitions);
let timeout = null;
let resolved = false;
new Promise((resolve, reject) => {
emitter.once(''action'', resolve);
emitter.emit(''done'', {});
timeout = setTimeout(() => {
if (!resolved) {
reject(''Timedout!'');
}
clearTimeout(timeout);
}, 100);
}).then(((state) => {
resolved = true;
assert(state.action === ''DONE'', ''should change state'');
done();
}))
.catch((error) => {
assert.isNotOk(error,''Promise error'');
done();
});
});
});
En la consola obtengo un ''UnhandledPromiseRejectionWarning'' a pesar de que se llama a la función de rechazo ya que muestra instantáneamente el mensaje ''AssertionError: Promise error''
(nodo: 25754) UnhandledPromiseRejectionWarning: Rechazo de promesa no controlado (id de rechazo: 2): Error de promesa: Error de promesa: se espera que {Object (message, showDiff, ...)} sea falso 1) debe hacer la transición con el evento correcto
Y luego, después de 2 segundos me sale
Error: se excedió el tiempo de espera de 2000 ms. Asegúrese de que se llame a la devolución de llamada done () en esta prueba.
Lo cual es aún más extraño ya que se ejecutó la devolución de llamada catch (creo que por alguna razón el fallo de afirmación impidió el resto de la ejecución)
Ahora lo curioso, si comento el
assert.isNotOk(error...)
la prueba funciona bien sin ninguna advertencia en la consola.
Todavía ''falla'' en el sentido de que ejecuta la captura.
Pero aún así, no puedo entender estos errores con promesa.
¿Alguien puede iluminarme?
Aquí está mi experiencia con E7 async / await :
En caso de que tenga una función
async helperFunction()
llamada desde su prueba ... (una explicilty con la palabra clave
async
ES7, quiero decir)
→ asegúrese de llamar a eso como
await helperFunction(whateverParams)
(bueno, sí, naturalmente, una vez que sepa ...)
Y para que eso funcione (para evitar ''esperar es una palabra reservada''), su función de prueba debe tener un marcador asíncrono externo:
it(''my test'', async () => { ...
El problema es causado por esto:
.catch((error) => {
assert.isNotOk(error,''Promise error'');
done();
});
Si la afirmación falla, arrojará un error.
Este error hará que nunca se llame a
done()
porque el código se equivocó antes.
Eso es lo que causa el tiempo de espera.
El
"rechazo de la promesa
no controlada
"
también es causado por la afirmación fallida, porque si se arroja un error en un controlador
catch()
,
y no hay un controlador
catch()
posterior
, el error se tragará (como se explica en
este artículo
)
La advertencia
UnhandledPromiseRejectionWarning
alerta sobre este hecho.
En general, si desea probar el código basado en promesas en Mocha, debe confiar en el hecho de que Mocha ya puede manejar las promesas.
No debe usar
done()
, sino que debe devolver una promesa de su prueba.
Mocha detectará los errores por sí mismo.
Me gusta esto:
it(''should transition with the correct event'', () => {
...
return new Promise((resolve, reject) => {
...
}).then((state) => {
assert(state.action === ''DONE'', ''should change state'');
})
.catch((error) => {
assert.isNotOk(error,''Promise error'');
});
});
Las bibliotecas de aserciones en Mocha funcionan arrojando un error si la aserción no es correcta.
Lanzar un error resulta en una promesa rechazada, incluso cuando se lanza en la función ejecutora proporcionada al método
catch
.
.catch((error) => {
assert.isNotOk(error,''Promise error'');
done();
});
En el código anterior, el
error
objetado se evalúa como
true
por lo que la biblioteca de aserciones arroja un error ... que nunca se detecta.
Como resultado del error, nunca se llama al método
done
.
La devolución de llamada
done
Mocha acepta estos errores, por lo que simplemente puede finalizar todas las cadenas de promesa en Mocha con
.then(done,done)
.
Esto garantiza que siempre se llame al método realizado y que el error se informe de la misma manera que cuando Mocha detecta el error de la aserción en código síncrono.
it(''should transition with the correct event'', (done) => {
const cFSM = new CharacterFSM({}, emitter, transitions);
let timeout = null;
let resolved = false;
new Promise((resolve, reject) => {
emitter.once(''action'', resolve);
emitter.emit(''done'', {});
timeout = setTimeout(() => {
if (!resolved) {
reject(''Timedout!'');
}
clearTimeout(timeout);
}, 100);
}).then(((state) => {
resolved = true;
assert(state.action === ''DONE'', ''should change state'');
})).then(done,done);
});
Doy crédito a este artículo por la idea de usar .then (hecho, hecho) al probar promesas en Mocha.
Me enfrenté a este problema:
(nodo: 1131004) UnhandledPromiseRejectionWarning: rechazo de promesa no manejada (id de rechazo: 1): TypeError: res.json no es una función (nodo: 1131004) DeprecationWarning: los rechazos de promesa no manejados están en desuso. En el futuro, los rechazos de promesas que no se manejan terminarán el proceso de Node.j s con un código de salida distinto de cero.
Fue mi error, estaba reemplazando el objeto
res
en
then(function(res)
, así que cambié
res
para dar como resultado y ahora está funcionando.
Incorrecto
module.exports.update = function(req, res){
return Services.User.update(req.body)
.then(function(res){//issue was here, res overwrite
return res.json(res);
}, function(error){
return res.json({error:error.message});
}).catch(function () {
console.log("Promise Rejected");
});
Corrección
module.exports.update = function(req, res){
return Services.User.update(req.body)
.then(function(result){//res replaced with result
return res.json(result);
}, function(error){
return res.json({error:error.message});
}).catch(function () {
console.log("Promise Rejected");
});
Código de servicio:
function update(data){
var id = new require(''mongodb'').ObjectID(data._id);
userData = {
name:data.name,
email:data.email,
phone: data.phone
};
return collection.findAndModify(
{_id:id}, // query
[[''_id'',''asc'']], // sort order
{$set: userData}, // replacement
{ "new": true }
).then(function(doc) {
if(!doc)
throw new Error(''Record not updated.'');
return doc.value;
});
}
module.exports = {
update:update
}
Para aquellos que buscan el error / advertencia
UnhandledPromiseRejectionWarning
fuera de un entorno de prueba, probablemente sea porque nadie en el código se está ocupando del eventual error en una promesa:
Por ejemplo, este código mostrará la advertencia informada en esta pregunta:
new Promise((resolve, reject) => {
return reject(''Error reason!'');
});
(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!
y agregar el
.catch()
o manejar el error debería resolver la advertencia / error
new Promise((resolve, reject) => {
return reject(''Error reason!'');
}).catch(() => { /* do whatever you want here */ });
O usando el segundo parámetro en la función
then
new Promise((resolve, reject) => {
return reject(''Error reason!'');
}).then(null, () => { /* do whatever you want here */ });
Recibí este error al tropezar con sinon.
La solución es usar el paquete npm sinon-as-prometido al resolver o rechazar promesas con apéndices.
En vez de ...
sinon.stub(Database, ''connect'').returns(Promise.reject( Error(''oops'') ))
Utilizar ...
require(''sinon-as-promised'');
sinon.stub(Database, ''connect'').rejects(Error(''oops''));
También hay un método de resolución (tenga en cuenta la s al final).
Ver http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejections
Resolví este problema después de desinstalar webpack (reaccionar problema js).
sudo uninstall webpack