即使处理了被拒绝的承诺,仍在接收UnUnledledPromiseRejectionWarning [英] Receiving `UnhandledPromiseRejectionWarning` even though rejected promise is handled
问题描述
我构建了一个函数,该函数通过 Generator
进行迭代,该函数同时包含同步代码和 Promise
:
I have constructed a function which iterates through a Generator
containing both synchronous code and Promises
:
module.exports = {
isPromise (value) {
return typeof value === 'object' && value !== null && 'then' in value;
},
runGen (generatorFunc, startValue) {
let that = this,
i = 0;
function *iterator(resolve, reject) {
let runGeneratorFunc = generatorFunc(startValue),
yieldedOut = {done: false},
yieldIn;
while (!yieldedOut.done) {
console.log(i++, 'Ready for next iteration');
if (that.isPromise(yieldedOut.value)) {
console.log(i++, 'Pass promise to KeepIterating');
yieldIn = yield yieldedOut.value;
console.log(i++, 'Received value from promise');
if(yieldIn instanceof Error){
console.log(i++, 'Value was instance of Error');
try {
yieldedOut = runGeneratorFunc.throw(yieldIn)
}
catch(err){
console.log(i++, 'Throw Error');
throw(yieldIn);
}
} else {
yieldedOut = runGeneratorFunc.next(yieldIn);
}
} else {
try {
yieldIn = yieldedOut.value;
yieldedOut = runGeneratorFunc.next(yieldIn);
}
catch(err) {
runGeneratorFunc.throw(err);
reject(err);
}
}
}
resolve(yieldedOut.value);
}
return new Promise(function (resolve, reject) {
var runIterator = iterator(resolve, reject);
(function keepIterating(yieldIn) {
let yieldedOutPromise = runIterator.next(yieldIn);
if (!yieldedOutPromise.done) {
yieldedOutPromise.value.then(function (fulfilledValue) {
console.log('never gets here');
keepIterating(fulfilledValue);
});
yieldedOutPromise.value.catch(function (err) {
console.log(i++, 'Rejected promise catched');
if (err instanceof Error) {
try {
console.log(i++, 'Rejected promise is instance of Error');
let yieldedOut = runIterator.next(err);
keepIterating(yieldedOut);
}
catch (err) {
console.log(i++, 'Error propagated back out');
yieldedOutPromise.value.catch(() => {})
reject(err);
}
} else {
try {
let yieldedOut = runIterator.next(new Error(err));
keepIterating(yieldedOut);
}
catch (err) {
reject(err);
}
}
})
}
})();
});
}
}
现在,当我使用以下代码导入并运行它时:
Now when I import and run it using this code:
const md = require('./module');
function* dummy () {
yield Promise.reject(new Error('error1'));
}
md.runGen(dummy)
.catch(err => {
console.log(9, 'Finished!');
})
我将其记录到控制台:
0 'Ready for next iteration'
1 'Ready for next iteration'
2 'Promise yielded out'
3 'Rejected promise handled'
4 'Rejected promise instance of Error'
5 'Ready to handle promise value'
6 'Value was instance of Error'
7 'Throw Error'
8 'Error propagated back out'
9 'Finished!'
(node:9904) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: error1
(node:9904) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
除了关于 UnhandledPromiseRejectionWarning $ c的警告外,其余均与预期的一样$ c>。我对为什么收到此警告感到困惑,因为据我所知,在代码中处理了被拒绝的
Promise
。
This is all as expected except for the warning about UnhandledPromiseRejectionWarning
. I am confused about why I receive this warning as the rejected Promise
is handled in the code as far as I can tell.
我俯瞰什么?
推荐答案
我是什么
What am I overlooking?
您的 yieldedOutPromise.value.then
调用正在创建新的承诺,并且如果 yieldedOutPromise.value
拒绝,则也会被拒绝。没关系,您可以通过 yieldedOutPromise.value
上的 .catch
处理错误,仍然存在被拒绝的承诺
Your yieldedOutPromise.value.then
call is creating a new promise, and if yieldedOutPromise.value
rejects then it will be rejected as well. It doesn't matter that you handle the error via .catch
on yieldedOutPromise.value
, there's still a rejected promise around, and it's the one that will be reported.
您基本上是在拆分承诺链,这导致每一端都需要一个错误处理程序。但是,您根本不应拆分任何内容。而不是
You are basically splitting your promise chain, which leads to each end needing an error handler. However, you shouldn't be splitting anything at all. Instead of the
promise.then(onSuccess);
promise.catch(onError);
应使用的反图案
promise.then(onSuccess, onError).…
哦,而在这种情况下,避免使用 Promise
构造函数反模式。只需执行
Oh, and while you're at it, avoid the Promise
constructor antipattern. Just do
module.exports = function runGen (generatorFunc, startValue) {
return Promise.resolve(startValue).then(generatorFunc).then(generator => {
return keepIterating({done: false, value: undefined});
function keepIterating({done, value}) {
if (done) return value;
return Promise.resolve(value).then(fulfilledValue =>
generator.next(fulfilledValue)
, err =>
generator.throw(err)
).then(keepIterating);
}
});
};
这篇关于即使处理了被拒绝的承诺,仍在接收UnUnledledPromiseRejectionWarning的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!