Javascript NodeJS 未处理的PromiseRejectionWarning
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39716569/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NodeJS UnhandledPromiseRejectionWarning
提问by Jzop
So, I'm testing a component that relies on an event-emitter. To do so I came up with a solution using Promises with Mocha+Chai:
所以,我正在测试一个依赖于事件发射器的组件。为此,我想出了一个使用 Promises 和 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();
});
});
On the console I'm getting an 'UnhandledPromiseRejectionWarning' even though the reject function is getting called since it instantly shows the message 'AssertionError: Promise error'
在控制台上,即使调用了拒绝函数,我也会收到“UnhandledPromiseRejectionWarning”,因为它会立即显示消息“AssertionError: Promise error”
(node:25754) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): AssertionError: Promise error: expected { Object (message, showDiff, ...) } to be falsy 1) should transition with the correct event
(node:25754) UnhandledPromiseRejectionWarning: UnhandledPromiseRejectionWarning: Unhandled promise Rejection (rejection id: 2): AssertionError: Promise error: expected { Object (message, showDiff, ...) } to be falsy 1) 应该用正确的事件转换
And then, after 2 sec I get
然后,2秒后我得到
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
错误:超过 2000 毫秒的超时。确保在此测试中调用 done() 回调。
Which is even weirder since the catch callback was executed.(I think that for some reason the assert failure prevented the rest of the execution)
由于执行了 catch 回调,这甚至更奇怪。(我认为由于某种原因,断言失败阻止了其余的执行)
Now the funny thing, if I comment out the assert.isNotOk(error...)
the test runs fine with out any warning in the console. It stills 'fails' in the sense that it executes the catch.
But still, I can't understand these errors with promise. Can someone enlighten me?
现在有趣的是,如果我注释掉assert.isNotOk(error...)
测试运行良好,控制台中没有任何警告。从它执行捕获的意义上说,它仍然“失败”。
但是,我仍然无法通过承诺来理解这些错误。有人可以启发我吗?
回答by robertklep
The issue is caused by this:
问题是由以下原因引起的:
.catch((error) => {
assert.isNotOk(error,'Promise error');
done();
});
If the assertion fails, it will throw an error. This error will cause done()
never to get called, because the code errored out before it. That's what causes the timeout.
如果断言失败,它将抛出错误。这个错误会导致done()
never 被调用,因为代码在它之前出错了。这就是超时的原因。
The "Unhandled promise rejection"is also caused by the failed assertion, because if an error is thrown in a catch()
handler, and there isn't a subsequent catch()
handler, the error will get swallowed (as explained in this article). The UnhandledPromiseRejectionWarning
warning is alerting you to this fact.
在“未处理的承诺拒绝”也由断言失败造成的,因为如果一个错误在被抛出catch()
的处理程序,并没有后续的catch()
处理程序,错误将得到吞噬(说明这篇文章)。该UnhandledPromiseRejectionWarning
警告提醒您注意这一事实。
In general, if you want to test promise-based code in Mocha, you should rely on the fact that Mocha itself can handle promises already. You shouldn't use done()
, but instead, return a promise from your test. Mocha will then catch any errors itself.
一般来说,如果你想在 Mocha 中测试基于 promise 的代码,你应该依赖 Mocha 本身已经可以处理 promise 的事实。你不应该使用done()
,而是从你的测试中返回一个 promise。Mocha 将自己捕获任何错误。
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');
});
});
回答by danday74
I got this error when stubbing with sinon.
我在用 sinon 存根时遇到了这个错误。
The fix is to use npm package sinon-as-promisedwhen resolving or rejecting promises with stubs.
解决方法是在使用存根解决或拒绝承诺时使用 npm 包sinon-as-promised。
Instead of ...
代替 ...
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 (note the s on the end).
还有一个 resolves 方法(注意末尾的 s)。
See http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejections
见http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejections
回答by Matthew Orlando
The assertion libraries in Mocha work by throwing an error if the assertion was not correct. Throwing an error results in a rejected promise, even when thrown in the executor function provided to the catch
method.
如果断言不正确,Mocha 中的断言库通过抛出错误来工作。抛出错误会导致被拒绝的承诺,即使在提供给catch
方法的执行程序函数中抛出也是如此。
.catch((error) => {
assert.isNotOk(error,'Promise error');
done();
});
In the above code the error
objected 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. Mocha's done
callback accepts these errors, so you can simply end all promise chains in Mocha with .then(done,done)
. This ensures that the done method is always called and the error would be reported the same way as when Mocha catches the assertion's error in synchronous code.
在上面的代码中,对象的error
计算结果为,true
所以断言库抛出一个错误......这是永远不会被捕获的。由于错误,该done
方法从未被调用。Mocha 的done
回调接受这些错误,所以你可以简单地用.then(done,done)
. 这确保了 done 方法总是被调用,并且错误会以与 Mocha 在同步代码中捕获断言错误时相同的方式报告。
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 give credit to this articlefor the idea of using .then(done,done) when testing promises in Mocha.
我将这篇文章归功于在 Mocha 中测试 promise 时使用 .then(done,done) 的想法。
回答by gsalgadotoledo
For those who are looking for the error/warning UnhandledPromiseRejectionWarning
outside of a testing environment, It could be probably because nobody in the code is taking care of the eventual error in a promise:
对于那些UnhandledPromiseRejectionWarning
在测试环境之外寻找错误/警告的人来说,这可能是因为代码中没有人处理承诺中的最终错误:
For instance, this code will show the warning reported in this question:
例如,此代码将显示此问题中报告的警告:
new Promise((resolve, reject) => {
return reject('Error reason!');
});
(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!
(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!
and adding the .catch()
or handling the error should solve the warning/error
并添加.catch()
或处理错误应该解决警告/错误
new Promise((resolve, reject) => {
return reject('Error reason!');
}).catch(() => { /* do whatever you want here */ });
Or using the second parameter in the then
function
或者使用then
函数中的第二个参数
new Promise((resolve, reject) => {
return reject('Error reason!');
}).then(null, () => { /* do whatever you want here */ });
回答by Frank Nocke
Here's my take experience with E7 async/await:
这是我使用E7 async/await 的经验:
In case you have an async helperFunction()
called from your test... (one explicilty with the ES7 async
keyword, I mean)
万一你有一个async helperFunction()
来自你的测试的调用......(async
我的意思是一个带有 ES7关键字的明确)
→ make sure, you call that as await helperFunction(whateverParams)
(well, yeah, naturally, once you know...)
→ 确保,你称之为await helperFunction(whateverParams)
(嗯,是的,自然,一旦你知道......)
And for that to work (to avoid ‘await is a reserved word'), your test-function must have an outer async marker:
为了使其工作(为了避免“等待是保留字”),您的测试函数必须有一个外部异步标记:
it('my test', async () => { ...
回答by Muhammad Shahzad
I faced this issue:
我遇到了这个问题:
(node:1131004) UnhandledPromiseRejectionWarning: Unhandled promise rejection (re jection id: 1): TypeError: res.json is not a function (node:1131004) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.j s process with a non-zero exit code.
(node:1131004) UnhandledPromiseRejectionWarning: 未处理的承诺拒绝 (rejection id: 1): TypeError: res.json is not a function (node:1131004) DeprecationWarning: 未处理的承诺拒绝被弃用。将来,未处理的承诺拒绝将以非零退出代码终止 Node.js 进程。
It was my mistake, I was replacing res
object in then(function(res)
, so changed res
to result and now it is working.
这是我的错误,我正在替换 中的res
对象then(function(res)
,因此更改res
为 result 并且现在可以正常工作了。
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
}
回答by Richard
I had a similar experience with Chai-Webdriver for Selenium.
I added await
to the assertion and it fixed the issue:
我对 Selenium 的 Chai-Webdriver 也有类似的经验。我添加await
了断言并解决了问题:
Example using Cucumberjs:
使用 Cucumberjs 的示例:
Then(/I see heading with the text of Tasks/, async function() {
await chai.expect('h1').dom.to.contain.text('Tasks');
});
回答by Mr Fun
I solved this problem after uninstalling webpack (react js problem ).
我在卸载 webpack 后解决了这个问题(react js 问题)。
sudo uninstall webpack