NodeJS UnhandledPromiseRejectionWarning

So, I am testing a component that relies on an event source. For this, I proposed a solution using Promises with 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(); }); }); 

In the console, I get "UnhandledPromiseRejectionWarning", although the reject function is called because it instantly displays the message "AssertionError: Promise Error"

(node: 25754) UnhandledPromiseRejectionWarning: raw promise reject (reject ID: 2): AssertionError: promise error: expected {Object (message, showDiff, ...)} to be false 1) must go with the correct event

And then, after 2 seconds, I get

Error: Exceeded latency 2000 ms. Make sure the done () callback is called in this test.

What's even weirder, since the catch callback was executed (I think for some reason the assert error prevented the completion of execution)

The funny thing is, if I comment out assert.isNotOk(error...) , the test will work without any warning in the console. He still “fails” in the sense that he is doing the job.
But still I can not understand these errors with a promise. Can anyone enlighten me?

+111
javascript promise mocha chai
Sep 27 '16 at 5:23
source share
7 answers

The problem is caused by the following:

 .catch((error) => { assert.isNotOk(error,'Promise error'); done(); }); 

If the statement fails, it throws an error. This error will cause done() never be called because the code was wrong before that. This is what causes the timeout.

“Refusing a raw promise” is also caused by a failed statement because if an error occurs in the catch() handler and there is no subsequent catch() handler, the error will be swallowed (as explained in this article ). The UnhandledPromiseRejectionWarning warning alerts you to this fact.

In general, if you want to test promise-based code in Mocha, you must rely on the fact that Mocha itself can handle promises already. You should not use done() , but instead return the promise from your test. Mocha will then catch any bugs.

Like this:

 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'); }); }); 
+139
Sep 27 '16 at 7:27
source share

I got this error while muting using sinon.

The fix is ​​to use the npm sinon-as-promised package when resolving or rejecting promises with stubs.

Instead...

 sinon.stub(Database, 'connect').returns(Promise.reject( Error('oops') )) 

Use ...

 require('sinon-as-promised'); sinon.stub(Database, 'connect').rejects(Error('oops')); 

There is also a resolves method (pay attention to the end).

See http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejected

+9
Oct 21 '16 at 4:52
source share

Mocha's assertion libraries work by throwing an error if the assertion was incorrect. If an error occurs, the promise is rejected even if it was issued in the executor function provided to the catch method.

 .catch((error) => { assert.isNotOk(error,'Promise error'); done(); }); 

In the above code, the objection error evaluates to true so the assertion library throws an error ... which is never caught. As a result of the error, the done method is never called. The Mocha done callback accepts these errors, so you can simply end all Mocha's promise chains with .then(done,done) . This ensures that the done method is always invoked, and the error will be reported as when Mocha catches a confirmation error in synchronous code.

 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); }); 

I pay tribute to this article for the idea of ​​using .then (done, done) when testing promises in Mocha.

+8
Jun 09 '17 at 20:54 on
source share

For those who are looking for the UnhandledPromiseRejectionWarning error / warning UnhandledPromiseRejectionWarning outside the testing environment, this may be due to the fact that no one in the code cares about a possible error in the promise:

For example, this code will show a warning in this question:

 new Promise((resolve, reject) => { return reject('Error reason!'); }); 

(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!

and adding .catch() or error handling should fix the warning / error

 new Promise((resolve, reject) => { return reject('Error reason!'); }).catch(() => { /* do whatever you want here */ }); 

Or using the second parameter in the then function

 new Promise((resolve, reject) => { return reject('Error reason!'); }).then(null, () => { /* do whatever you want here */ }); 
+5
Apr 05 '18 at 4:53 on
source share

Here is my experience with E7 async / await :

If you have async helperFunction() called from your test ... (one of the explanations with the ES7 async , I mean)

→ make sure you call it await helperFunction(whateverParams) (well yes, of course, as soon as you know ...)

And for this to work (to avoid "waiting is a reserved word), your test function must have an external asynchronous token:

 it('my test', async () => { ... 
+1
Oct 30 '17 at 16:27
source share

I solved this problem after removing the web package (responds to a problem with js).

 sudo uninstall webpack 
+1
Jun 16 '19 at 12:59 on
source share

I ran into this problem:

(node: 1131004) UnhandledPromiseRejectionWarning: rejection of an unhandled promise (re jection id: 1): TypeError: res.json is not a function (node: 1131004) Refusal. Warning. Deviations from the raw promise are out of date. In the future, a promise of rejection that is not processed will lead to the end of Node.js with a non-zero exit code.

It was my mistake, I replaced the res object in then(function(res) , so I changed res to the result, and now it works.

Wrong

 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"); }); 

Correction

 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"); }); 

Service Code:

 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 } 
0
May 03 '17 at 19:22
source share



All Articles