我在我的專案中使用 @typescript-eslint/no-floating-promises
規則。如果我寫這樣的程式碼,這條規則就會抱怨 -
functionReturningPromise() .then(retVal => doSomething(retVal));
它希望我為此 Promise
添加一個 catch
區塊。如果我想在異常處理區塊中添加一些邏輯,這對我來說是有意義的。但是,在很多情況下我不需要它。我對拋出的錯誤很滿意。因此,為了抑制此規則引發的錯誤,我最終這樣做了 -
functionReturningPromise() .then((retVal) => doSomething(retVal)) .catch((error) => { throw error; });即使我沒有像上面那樣添加
catch
區塊,error
仍然會以相同的方式拋出(至少在我的控制台輸出中看到它)。因此,我不明白明確指定此 catch
區塊的意義。我錯過了什麼嗎?如果我新增/不新增 catch
區塊,拋出 error
的方式真的有差別嗎? P粉1067114252024-03-20 17:42:08
評論者都很好地回答了您的問題 - 但為了透過範例說明為什麼這很重要,請想像以下程式碼:
Promise.reject(); setTimeout(() => console.log('hello'), 1000);
這段程式碼看起來相當無害 - 有一個未處理的無操作承諾拒絕,啟動後 1 秒程式將記錄 'hello'
。
在瀏覽器中 - 這正是將會發生的情況 - 瀏覽器將記錄「未捕獲的承諾拒絕」錯誤,但否則會忽略它。
然而,在 NodeJS(從 Node v15 開始)中,未處理的 Promise 拒絕是一個硬錯誤 - 這表示進程在偵測到錯誤時將退出!
您可以透過在終端機中執行程式碼來驗證這一點(-e
的意思是「評估並執行此程式碼字串」)
$ node -e "Promise.reject(); setTimeout(() => console.log('hello'), 1000)" node:internal/process/promises:288 triggerUncaughtException(err, true /* fromPromise */); ^ [UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected the was not handled with .catch(). The promise rejected the code: 'ERR_UNHANDLED_REJECTION' } Node.js v18.12.1
您可以看到 'hello'
永遠不會被列印,因為進程在 1 秒之前終止!
要驗證事情是否按預期工作,您可以將 .reject
更改為 .resolve
:
$ node -e "Promise.resolve(); setTimeout(() => console.log('hello'), 1000)" hello
因此,如果您正在使用任何 LTS 支援的版本編寫 NodeJS 應用程序,那麼您絕對應該處理錯誤,否則您將面臨意外崩潰的風險。
如果您的程式碼僅在瀏覽器中運行,那麼您可能想知道是否應該處理失敗- 畢竟您的用戶沒有查看控制台,因此他們不會知道發生了任何不好的事情,所以誰在乎呢?從“僅代碼”的角度來看,您是正確的 - 但是,當出現問題時,您的用戶希望從他們的應用程式中獲得反饋。
想像以下場景 - 您的 Promise 追蹤 API 呼叫的結果,該呼叫提交用戶在您的應用程式中輸入的一些資料。如果該 API 呼叫由於某種原因失敗,那麼您的應用程式應該做出適當的回應並告訴使用者出了問題。
處理它的替代方法可能意味著您的應用程式顯示無限載入旋轉器,或者使用者認為他們的資料已成功提交,但實際上並未成功。無論哪種方式 - 這是一個非常糟糕且破碎的用戶體驗!
最後做一些像 .catch(e => { throw e })
這樣的事情,你其實並沒有處理錯誤。當然,這段程式碼會使 linter 保持沉默 - 但您所做的只是創建一個新的、被拒絕的承諾,該承諾將記錄到控制台。相反,您應該以某種方式將錯誤連接到應用程式的 UI,例如像 .catch(e => {alert(e); throw e })
這樣簡單的東西會更好。