promise 鏈中出現錯誤時,會順著鏈接去到最近的錯誤處理函式。也可以說最簡單的處理方式就是在鏈接的尾端加上 catch,來抓所有錯誤,很類似一般的 try...catch 結構:
doSomething()
  .then((result) => doSomethingElse(result))
  .then((newResult) => doThirdThing(newResult))
  .then((finalResult) => console.log(`Got the final result: ${finalResult}`))
  .catch(failureCallback);
promise executor 或各處理函式中只要出現錯誤,無論是 promise 本身失敗、丟出例外或程式錯誤,都會有如同 rejected promise 的表現,可以在 catch 中接到處理。例如以下兩段會得到一樣的錯誤:
// 1
new Promise((resolve, reject) => {
    throw new Error('Whoops!');
}).catch(alert); // Error: Whoops!
// 2
new Promise((resolve, reject) => {
    reject(new Error('Whoops!'));
}).catch(alert); // Error: Whoops!
如果沒有處理,發生錯誤會造成程式中斷。這時候瀏覽器的 JS 引擎會產生一個全域錯誤,可以用 'unhandledrejection' 事件追蹤到,這段有更詳細的範例解說。
程式碼要不要巢狀撰寫除了可讀性和個人習慣外,也可以考慮這種結構會造成的實際影響。這部分可參考前一篇最後一個例子。
巢狀的一個效果是會限制 catch 的作用範圍,它變成只會抓到內層的錯誤,善加運用這點可以做到更精確的錯誤處理:
doSomethingCritical()
    .then((result) =>
        doSomethingOptional(result)
            .then((optionalResult) => doSomethingExtra(optionalResult))
            .catch((e) => {}),  // 第 5 行
        ) 
    // 無論 doSomethingOptional 成功失敗都會進行
    .then(() => moreCriticalStuff())
    .catch((e) => console.error(`Critical failure: ${e.message}`));
這樣的結構有一些特性
catch 只會處理 doSomethingOptional 和 doSomethingExtra 的錯誤。並且有處理後錯誤自然就不會再跑到外面去。一般而言,最佳做法是盡量不要有巢狀,鏈接越平越好,但必要時也可以利用結構來做適當的程式碼控制。