visual studio node guide docs debug community code javascript node.js promise mocha chai

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