2 回答

TA貢獻1812條經(jīng)驗 獲得超5個贊
我的函數(shù)以“即發(fā)即忘”的方式調(diào)用私有異步函數(shù),并且不添加任何錯誤處理。
不要那樣做。
外部庫處理所有未捕獲的承諾拒絕。在生產(chǎn)中,我希望 shell 來處理它,所以我不想在函數(shù)本身中處理它。
不要依賴這個外部庫。
您應(yīng)該在函數(shù)中使用自己的全局錯誤處理函數(shù)。
在生產(chǎn)中,讓該錯誤處理函數(shù)簡單地重新拋出異常,以便環(huán)境能夠捕獲該異常,或者更好的是,如果可能的話,直接調(diào)用 shell 錯誤處理函數(shù)。
在測試中,您可以模擬自己的全局處理程序,并斷言它是使用預(yù)期參數(shù)調(diào)用的。

TA貢獻1835條經(jīng)驗 獲得超7個贊
processAction是同步的并且不知道 Promise,這會導(dǎo)致懸空的 Promise。懸空承諾永遠不應(yīng)該拒絕,因為這會導(dǎo)致未經(jīng)處理的拒絕,這是一種例外。根據(jù)環(huán)境的不同,這可能會導(dǎo)致應(yīng)用程序崩潰。即使異常是全局處理的,這也不應(yīng)該成為不處理預(yù)期錯誤的理由。
正確的方法是在fetchTheThing拒絕發(fā)生的地方明確抑制拒絕:
private async fetchTheThing() {
try {
...
} catch {} finally {
this.isFetching = false;
}
}
或者在這種情況下,它更像processAction是導(dǎo)致懸而未決的承諾:
this.fetchTheThing().catch(() => {});
否則將調(diào)度未處理的拒絕事件。
如果沒有的話,可以通過監(jiān)聽事件來測試:
...
let onRej = jest.fn();
process.once('unhandledRejection', onRej);
rej();
await Promise.sleep();
expect(onRej).toBeCalled();
expect(store.isFetching).toBe(false);
如果已經(jīng)有另一個監(jiān)聽器,這將無法按預(yù)期工作unhandledRejection,這在良好的 Jest 設(shè)置中是可以預(yù)期的。如果是這種情況,唯一不會影響其他測試的解決方法是在測試之前重置它們并在測試之后重新添加:
let listeners;
beforeEach(() => {
listeners = process.rawListeners('unhandledRejection');
process.removeAllListeners('unhandledRejection');
});
afterEach(() => {
(typeof listeners === 'function' ? [listeners] : listeners).forEach(listener => {
process.on('unhandledRejection', listener);
});
})
不建議這樣做,使用時應(yīng)自行承擔風險,因為這表明錯誤處理存在更深層次的問題,而在正確設(shè)計的 JavaScript 應(yīng)用程序中通常不可接受。
添加回答
舉報