即使被拒绝的承诺被处理,也会收到`UnhandledPromiseRejectionWarning`

我已经构build了一个函数,它遍历一个包含同步代码和PromisesGenerator

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

我得到这个logging到控制台:

 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的警告之外,这一切都是预期的。 我很困惑,为什么我收到这个警告,因为被拒绝的Promise 在代码中处理的,据我所知。

我忽略了什么?

我忽略了什么?

您的yieldedOutPromise.value.then调用正在创build一个新的承诺,如果yieldedOutPromise.value拒绝,那么它也将被拒绝。 通过.catch on yieldedOutPromise.value处理错误并没有关系,但是仍然有一个被拒绝的承诺,并且会被报告。

你基本上是分裂你的承诺链,导致每个端点需要一个error handling程序。 但是,你不应该分裂任何东西。 而不是

 promise.then(onSuccess); promise.catch(onError); 

反模式,你应该使用

 promise.then(onSuccess, onError).… 

哦,当你在这里, 避免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); } }); };