有没有办法检测被拒绝的承诺是否未处理? [英] Is there a way detect if a rejected promise is unhandled?

查看:19
本文介绍了有没有办法检测被拒绝的承诺是否未处理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个函数 foo 返回一个 promise.有没有办法调用该函数,并且只有在未处理拒绝的情况下才可以选择 Promise.prototype.catch 调用结果?我想要一个适用于 node.js 和浏览器的解决方案.例如:

const fooResult = foo();//将 fooResult 传递到其他地方,在那里 fooResult 可能会被 catch 捕获catchIfUncaught(fooResult, (err) => {控制台日志(错误);//只有在其他地方没有发现拒绝时才应该是 foo 拒绝//没有未处理的拒绝发生});

解决方案

不,没有.当您的函数返回一个承诺时,将错误处理留给调用者 - 如果他错过这样做,他将收到一个 unhandledpromiserejection 事件.

<小时>

我能想到的唯一技巧就是识别 then 调用,然后取消你自己的错误处理:

function catchIfUncaught(promise, handler) {让处理=假;promise.catch(err => {如果(!处理)处理程序(错误);});promise.then = function(onFulfilled, onRejected) {处理 = 真;返回 Promise.prototype.then.call(this, onFulfilled, onRejected);};回报承诺;}

示例:

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("然后拒绝处理程序", 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 => {});//未处理的拒绝(在链式承诺上)

如您所见,这仅在您的函数的调用者完全忽略结果时才有用 - 这确实不常见.如果他这样做了,我建议仍然让调用者处理错误.

<小时>

我之前设计的一个类似的技巧是使用 handler 作为默认的onRejected:

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

这将在 catchIfUncaught(…).then(res => …); 情况下激活默认处理程序,但对于较长链中的调用者来说可能非常违反直觉.>

另请注意,这两种 hack 都不能与 await 一起正常工作,它们总是导致调用者需要捕获的异常.对于任何其他需要 thenable 的内置函数也是如此——它们总是用两个参数调用 .then.

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

解决方案

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.

这篇关于有没有办法检测被拒绝的承诺是否未处理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆