2 回答
TA贡献1812条经验 获得超5个赞
我的函数以“即发即忘”的方式调用私有异步函数,并且不添加任何错误处理。
不要那样做。
外部库处理所有未捕获的承诺拒绝。在生产中,我希望 shell 来处理它,所以我不想在函数本身中处理它。
不要依赖这个外部库。
您应该在函数中使用自己的全局错误处理函数。
在生产中,让该错误处理函数简单地重新抛出异常,以便环境能够捕获该异常,或者更好的是,如果可能的话,直接调用 shell 错误处理函数。
在测试中,您可以模拟自己的全局处理程序,并断言它是使用预期参数调用的。
TA贡献1835条经验 获得超7个赞
processAction是同步的并且不知道 Promise,这会导致悬空的 Promise。悬空承诺永远不应该拒绝,因为这会导致未经处理的拒绝,这是一种例外。根据环境的不同,这可能会导致应用程序崩溃。即使异常是全局处理的,这也不应该成为不处理预期错误的理由。
正确的方法是在fetchTheThing拒绝发生的地方明确抑制拒绝:
private async fetchTheThing() {
try {
...
} catch {} finally {
this.isFetching = false;
}
}
或者在这种情况下,它更像processAction是导致悬而未决的承诺:
this.fetchTheThing().catch(() => {});
否则将调度未处理的拒绝事件。
如果没有的话,可以通过监听事件来测试:
...
let onRej = jest.fn();
process.once('unhandledRejection', onRej);
rej();
await Promise.sleep();
expect(onRej).toBeCalled();
expect(store.isFetching).toBe(false);
如果已经有另一个监听器,这将无法按预期工作unhandledRejection,这在良好的 Jest 设置中是可以预期的。如果是这种情况,唯一不会影响其他测试的解决方法是在测试之前重置它们并在测试之后重新添加:
let listeners;
beforeEach(() => {
listeners = process.rawListeners('unhandledRejection');
process.removeAllListeners('unhandledRejection');
});
afterEach(() => {
(typeof listeners === 'function' ? [listeners] : listeners).forEach(listener => {
process.on('unhandledRejection', listener);
});
})
不建议这样做,使用时应自行承担风险,因为这表明错误处理存在更深层次的问题,而在正确设计的 JavaScript 应用程序中通常不可接受。
添加回答
举报