有没有办法检测被拒绝的承诺是否未处理?
Is there a way detect if a rejected promise is unhandled?
假设我有一个函数 foo
,它 returns 是一个承诺。有没有一种方法可以调用该函数,并且只有在拒绝未处理的情况下才可以选择 Promise.prototype.catch
结果?我想要一个适用于 node.js 和浏览器的解决方案。例如:
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
});
如果您不关心传递的情况,您可以只捕获错误情况。
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
不,没有。当你的函数 returns 是一个承诺时,这会将错误处理留给调用者 - 如果他没有做到这一点,他将得到一个 unhandledpromiserejection
事件。
我能想到的唯一技巧是识别 then
调用,然后取消您自己的错误处理:
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;
}
示例:
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)
如您所见,这仅在函数的调用者完全忽略结果时才有用——这种情况很少见。如果他这样做,我建议仍然 .
将使用 handler
作为 onRejected
的默认值:
…
promise.then = function(onFulfilled, onRejected = handler) {
// ^^^^^^^^^
return Promise.prototype.then.call(this, onFulfilled, onRejected);
};
这会在 catchIfUncaught(…).then(res => …);
情况下激活默认处理程序,但对于较长链中的调用者来说可能非常违反直觉。
另请注意,这两个 hack 都不能与 await
一起正常工作,它们总是会导致调用者需要捕获的异常。对于任何其他期望 thenable 的内置函数也是如此 - 他们总是用两个参数调用 .then
。
你可以看看这个包https://npmjs.org/package/e-promises
但您必须更改代码才能使用新机制
- 导入
EPromise
- 使用
YourPromise extends EPromise
扩展它(可选)
- 将
YourPromise.prototype.unchaught
分配给您的 catchIfUncaught
实施
- 更改
foo
中的代码,每个承诺的地方必须更改为使用YourPromise
,等等new YourPromise(executor) / YourPromise.resolve / YourPromise.all / ...
假设我有一个函数 foo
,它 returns 是一个承诺。有没有一种方法可以调用该函数,并且只有在拒绝未处理的情况下才可以选择 Promise.prototype.catch
结果?我想要一个适用于 node.js 和浏览器的解决方案。例如:
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
});
如果您不关心传递的情况,您可以只捕获错误情况。
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
不,没有。当你的函数 returns 是一个承诺时,这会将错误处理留给调用者 - 如果他没有做到这一点,他将得到一个 unhandledpromiserejection
事件。
我能想到的唯一技巧是识别 then
调用,然后取消您自己的错误处理:
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;
}
示例:
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)
如您所见,这仅在函数的调用者完全忽略结果时才有用——这种情况很少见。如果他这样做,我建议仍然
handler
作为 onRejected
的默认值:
…
promise.then = function(onFulfilled, onRejected = handler) {
// ^^^^^^^^^
return Promise.prototype.then.call(this, onFulfilled, onRejected);
};
这会在 catchIfUncaught(…).then(res => …);
情况下激活默认处理程序,但对于较长链中的调用者来说可能非常违反直觉。
另请注意,这两个 hack 都不能与 await
一起正常工作,它们总是会导致调用者需要捕获的异常。对于任何其他期望 thenable 的内置函数也是如此 - 他们总是用两个参数调用 .then
。
你可以看看这个包https://npmjs.org/package/e-promises
但您必须更改代码才能使用新机制
- 导入
EPromise
- 使用
YourPromise extends EPromise
扩展它(可选) - 将
YourPromise.prototype.unchaught
分配给您的catchIfUncaught
实施 - 更改
foo
中的代码,每个承诺的地方必须更改为使用YourPromise
,等等new YourPromise(executor) / YourPromise.resolve / YourPromise.all / ...