有没有一种方法可以检测是否未兑现被拒绝的承诺?

时间:2019-09-04 14:45:59

标签: javascript node.js promise es6-promise

假设我有一个返回承诺的函数foo。是否有一种方法可以调用该函数,并且只有在未解决拒绝的情况下,才可以选择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
});

3 个答案:

答案 0 :(得分:1)

不,没有。当您的函数返回一个Promise时,错误处理留给了调用者-如果他错过了,他将得到一个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)

如您所见,这仅在函数的调用者完全忽略结果时才有用-的确很少见。如果他愿意,我建议您仍然let the caller handle errors


A similar hack I devised earlier将使用handler作为onRejected的默认值:

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

这将在catchIfUncaught(…).then(res => …);情况下激活默认处理程序,但在较长的链中可能与调用方有很强的直觉。

还要注意,这两种骇客都无法与await一起正常工作,它们总是导致呼叫者需要捕获的异常。同样,对于任何其他期望有可能实现的内置函数-它们总是使用两个参数调用.then

答案 1 :(得分:0)

你可以看看这个包https://npmjs.org/package/e-promises

但是您必须更改代码才能使用新机制

  1. 导入 EPromise
  2. 使用 YourPromise extends EPromise(可选)扩展它
  3. YourPromise.prototype.unchaught 分配给您的 catchIfUncaught 实现
  4. 更改foo中的代码,每个做出承诺的地方都必须更改为使用YourPromisenew YourPromise(executor) / YourPromise.resolve / YourPromise.all / ...

答案 2 :(得分:-1)

如果您不关心传递的情况,则可以捕获错误情况。

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

相关问题