【JavaScript 筆記】 Promise chaining 的 catch 到底是在處理什麼錯誤?

Chengcheng Hsu
7 min readApr 4, 2022

--

Photo by Bo Lane on Unsplash

這篇主要是延續上一篇《【JavaScript 筆記】 這是你要的承諾 Promise》,我們都知道 catch 在處理錯誤,但到底哪些錯誤是由哪個 catch 在處理的,這個觀念在我腦中還算是滿模糊,所以這篇就來實地的走一次,並且釐清一下這些 catch 到底是在處理哪些錯誤,我們也可以想像成棒球比賽,各個區域皆有不同的守備人員在處理,各司其職。

看完這篇會知道以下問題的答案:

  1. API response 的 http status 是 500,是 Promise chaining 的 catch 會處理到,還是是在外面再包一層的 try/catch 會處理到?
  2. 用 fetch 來打 API ,但你把 fetch 不小心拼錯,是 Promise chaining 的 catch 會處理嗎,還是是在外面再包一層的 try/catch 會處理?
  3. 若 fetch 沒拼錯,但你把 fetch API 的網址打錯,Promise chaining 的 catch 會處理嗎,還是是在外面再包一層的 try/catch 會處理?
  4. 若 Promise chaining 內某個非同步的動作被 Promise catch 處理掉了,後面其他非同步的動作還會被執行嗎

前置作業 (1) — 用 Mocky 建立 API:

Mocky 官網 點擊 New Mock 來建立 API,第一個我們將 HTTP Status http status 選擇 200,Response Content Type 選擇 text/json,HTTP Response Body 隨意打上你要的 response,接著點擊 generate my http response 來產生 URL,另一個 API 的 HTTP Status http status 選擇 500,一樣點擊 generate my http response 來產生 URL,以下是我產生的 URL

http status 200 URL:

https://run.mocky.io/v3/b07d693b-c85f-4ad2-987c-b3b72f5f82c5

http status 500 URL:

https://run.mocky.io/v3/7e19376a-995b-4b6d-8f8c-2fd1912832c6

前置作業 (2) — 建立 Promise:

.html檔案的 <script>內去建立一個 func,它的回傳是一個 promise,當符合 id 等於 10 的條件下會 resolve 回傳一物件,當 id 不等於 10 的條件下會 reject 並回傳 reject in promise, unauthorized access to the user data

註記:可以用 .constructor.name來確認是否為 promise

釐清問題 — (1): API response 的 http status 是 500,會是 Promise chaining 的 catch 處理,還是外面包一層的 try/catch 會處理?

我們先使用 fetch 來打剛剛建立的 http status 是 200 的 API,並打開檔案 devtool 來看看是否能拿到 response

如預期拿到 response:

接著把 fetch 的 URL 改成 http status 是 500 的 API 來試試看

fetch("https://run.mocky.io/v3/7e19376a-995b-4b6d-8f8c-2fd1912832c6")

結果是我還是拿的到 response ,無論是 Promise chaining 的 catch ,還是外面包一層的 try/catch 都不會處理到,因為這個一個成功的 request/response,所以 http status 是 500 在這裡的 catch 並不會表示任何錯誤。

釐清問題 — (2): 把 fetch 不小心拼錯,會是 Promise chaining 的 catch 處理,還是外面包一層的 try/catch 會處理?

將 fetch 打成 fetchs:

結論是外層的 try/catch 會處理,因此如果是函式名稱打錯,或是任何寫法錯誤會被 try/catch 抓到錯誤

釐清問題 — (3): API 網址打錯,會是 Promise chaining 的 catch 處理,還是外面包一層的 try/catch 會處理?

在網址故意多加一個 1,來看看結果會是如何

結果是這個 fetch 的 status 是 failed 的,自然不會有 response,因此 Promises chaining 的 catch 會做處理

釐清問題 — (4): 前面的 promise 就被 Promise chaining 的 catch 處理掉了,其他非同步的動作還會被執行嗎?

我們一樣保留錯誤的網址,並且後面接打 http status 200 的 API

結果是一旦前面的 Promise 被 Promises chaining 的 catch 處理掉了,後面的 API 也都不會執行了

一樣,如果我們換成我們前置作業建立的 Promise,故意讓他的 promise 是以 reject 來回傳,結果還是還是一樣,後面的 API 也不會執行

會被 Promise chaining 的 catch 處理,並且內容是 promise reject 所定義的

結論:

  1. .then 的寫法是用來改善 callback func 的回呼地獄,並且是有順序性的,當某個非同步的動作處裡完才會處理另一個動作,最後以 .catch 來處理錯誤
  2. API 網址打錯誤是代表 fetch fail 了, request 打到錯誤的地方,自然不會有 response ,因此會被 Promise chaining Caught by .catch 抓到錯誤
  3. fetch 回來的 response http status 500 或是 400 並不會被 Promise chaining 的 catch 還是外面包一層的 try/catch 視為錯誤,因為整個 request/ response 算是成功的
  4. 如果是函式名稱打錯,或是任何寫法錯誤才會被外層的 try/catch 抓到錯誤
  5. 無論是 promise 結果是 reject,還是 fetch fail ,當 Promise chaining Caught by .catch 抓到錯誤,後續非同步的動作都不會執行到

--

--

Chengcheng Hsu
Chengcheng Hsu

Written by Chengcheng Hsu

Movie, Travel and Story | Software developer | contact me: ychsu.wk@gmail.com

No responses yet