Javascript 接收“UnhandledPromisejectionWarning”,即使已处理拒绝的承诺
我构造了一个函数,它通过一个Javascript 接收“UnhandledPromisejectionWarning”,即使已处理拒绝的承诺,javascript,node.js,runtime-error,generator,es6-promise,Javascript,Node.js,Runtime Error,Generator,Es6 Promise,我构造了一个函数,它通过一个生成器进行迭代,该生成器包含同步代码和承诺: module.exports = { isPromise (value) { return typeof value === 'object' && value !== null && 'then' in value; }, runGen (generatorFunc, startValue) { let
生成器
进行迭代,该生成器包含同步代码和承诺
:
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);
}
}
})
}
})();
});
}
}
现在,当我使用以下代码导入并运行它时:
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.
除了关于未处理PromisejectionWarning
的警告之外,这一切都与预期的一样。我不明白为什么我会收到这个警告,因为据我所知,被拒绝的承诺
是在代码中处理的
我忽略了什么
我忽略了什么
您的yieldedOutPromise.value.then
调用正在创建一个新的承诺,如果yieldedOutPromise.value
拒绝,那么它也将被拒绝。通过yieldedOutPromise.value
上的.catch
处理错误并不重要,仍然有一个被拒绝的承诺,它将被报告
您基本上是在分割承诺链,这导致每一端都需要一个错误处理程序。但是,您不应该拆分任何内容。而不是
promise.then(onSuccess);
promise.catch(onError);
您应该使用的反模式
promise.then(onSuccess, onError).…
哦,当你这么做的时候。照办
是否有语法错误?否输出与上面显示的完全相同。没有遗漏任何东西。你真的不应该自己编写这种函数。使用提供它的库(例如
Bluebird.coroutine
)或立即使用async
/wait
语法(使用适当的transpiler)。您建议的解决方案不会返回预期的结果。@guest271314您的意思是什么?OP得到的输出日志“预期结果”是什么?它为您返回了什么?您的方法没有到达console.log('never get here')代码>@guest271314。链接<代码>值。然后(…).catch(…)<代码>不是我们想要的。@链接中解释的Guest71314,您需要考虑<代码>完成的抛出的情况。诚然,这不会发生在您的代码中,只是因为您仍然使用promise构造函数反模式。
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);
}
});
};