有没有办法检测被拒绝的承诺是否未处理? [英] Is there a way detect if a rejected promise is unhandled?
问题描述
假设我有一个函数 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屋!