Is there a way detect if a rejected promise is unhandled?

时光毁灭记忆、已成空白 提交于 2019-12-20 04:25:06

问题


Let’s say I have a function foo which returns a promise. Is there a way to call the function, and optionally Promise.prototype.catch the result only if its rejection is unhandled? I want a solution which works in both node.js and the browser. For example:

const fooResult = foo();
// pass fooResult somewhere else where fooResult may be caught with catch
catchIfUncaught(fooResult, (err) => {
  console.log(err); // should be foo rejection only if the rejection is not caught elsewhere
  // no unhandled rejection occurs
});

回答1:


No, there is not. When your function returns a promise, that leaves error handling to the caller - and he'll get an unhandledpromiserejection event if he misses to do that.


The only hack I can imagine would be to recognise then calls, and then cancel your own error handling:

function catchIfUncaught(promise, handler) {
    let handled = false;
    promise.catch(err => {
        if (!handled)
             handler(err);
    });
    promise.then = function(onFulfilled, onRejected) {
        handled = true;
        return Promise.prototype.then.call(this, onFulfilled, onRejected);
    };
    return promise;
}

Examples:

catchIfUncaught(Promise.reject(), err => console.log("default handler", err));

catchIfUncaught(Promise.reject(), err => console.log("default handler", err))
.catch(err => console.log("catch handler", err));

catchIfUncaught(Promise.reject(), err => console.log("default handler", err))
.then(null, err => console.log("then rejection handler", err));

catchIfUncaught(Promise.reject(), err => console.log("default handler", err))
.then(res => {})
.catch(err => console.log("chained catch handler", err));

catchIfUncaught(Promise.reject(), err => console.log("default handler", err))
.then(res => {});
// unhandled rejection (on the chained promise)

As you can see, this is only useful when the caller of your function completely ignores the result - which is really uncommon. And if he does, I'd recommend to still let the caller handle errors.


A similar hack I devised earlier would be to use the handler as the default for onRejected:

…
promise.then = function(onFulfilled, onRejected = handler) {
//                                              ^^^^^^^^^
    return Promise.prototype.then.call(this, onFulfilled, onRejected);
};

This would activate the default handler in the catchIfUncaught(…).then(res => …); case, but probably be highly counter-intuitive to the caller in longer chains.

Also notice that neither of these two hacks work properly together with await, where they always lead to an exception that the caller needs to catch. And same for any other builtin that expects a thenable - they always call .then with two arguments.




回答2:


You can just catch the error case, if you don't care about the passing case.

catchIfUncaught.catch(function (err) {
  console.error('We had an error: ', err)
})

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch



来源:https://stackoverflow.com/questions/57790880/is-there-a-way-detect-if-a-rejected-promise-is-unhandled

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!