今天我們來學習在Promise中如何處理異常錯誤。
假設有一個getUserById
函數用來獲取用戶,它返回一個promise。
function getUserById(id) { return new Promise((resolve, reject) => { resolve({ id: id, username: 'admin' }); }); }
throw new Error
在返回promise之前,如果id參數不合法throw一個異常
function getUserById(id) { if (typeof id !== 'number' || id <= 0) { throw new Error('參數ID不合法'); } return new Promise((resolve, reject) => { resolve({ id: id, username: 'admin' }); }); }
接着,調用這個promise,設置then、catch回調
getUserById('a') .then(user => console.log(user.username)) .catch(error => console.log(error)); // 輸出: // Uncaught Error: 參數ID不合法
可以看到,then、catch都不會走,如果要捕獲這個錯誤,必須要用try/catch
try { getUserById('a') .then(user => console.log(user.username)) .catch(error => console.log(`.catch被調用:${error}`)); } catch (error) { console.log(`try/catch被調用:${error}`); } // 輸出: // try/catch被調用:Error: 參數ID不合法
在try/catch內成功捕獲錯誤。
在Promise內throw
在promise內拋出異常
let authorized = false; function getUserById(id) { return new Promise((resolve, reject) => { if (!authorized) { throw new Error('未登錄,獲取用戶信息失敗'); } resolve({ id: id, username: 'admin' }); }); }
調用
try { getUserById(10) .then(user => console.log(user.username)) .catch(error => console.log(`.catch被調用:${error}`)); } catch (error) { console.log(`try/catch被調用:${error}`); } // 輸出: // .catch被調用:Error: 未登錄,獲取用戶信息失敗
如果在promise內去throw拋出異常,則可以在.catch的回調中捕獲到,在try/catch中無法捕獲
如果使用鏈式調用promise,.catch將捕獲任何一個promise的異常錯誤
promise1 .then(promise2) .then(promise3) .then(promise4) .catch(err => console.log(err));
在上面的例子里,如果promise1、promise2有異常都會被.catch捕獲到。
使用reject()
函數
使用reject()函數和上面throw拋出異常一樣,
let authorized = false; function getUserById(id) { return new Promise((resolve, reject) => { if (!authorized) { reject('未登錄,獲取用戶信息失敗'); } resolve({ id: id, username: 'admin' }); }); } try { getUserById(10) .then(user => console.log(user.username)) .catch(error => console.log(`.catch被調用:${error}`)); } catch (error) { console.log(`try/catch被調用:${error}`); } // 輸出: // .catch被調用:未登錄,獲取用戶信息失敗
在上面例子里,我們沒有在promise內throw異常,而是調用reject()函數。同樣也是在.catch被捕獲。
沒有.catch()方法會怎樣
下面的例子里沒有為promise提供.catch回調來捕獲錯誤
let authorized = false; function getUserById(id) { return new Promise((resolve, reject) => { if (!authorized) { reject('未登錄,獲取用戶信息失敗'); } resolve({ id: id, username: 'admin' }); }); } try { getUserById(10) .then(user => console.log(user.username)); // 下面的代碼會執行 console.log('next'); } catch (error) { console.log(`try/catch被調用:${error}`); } // 輸出: // next // Uncaught (in promise) 未登錄,獲取用戶信息失敗
如果promise被resolve,則可以省略catch()回調。上面console.log('next')將會執行。
總結
在promise中,.catch()函數會捕獲promise內的throw錯誤和reject拋出的錯誤。
如果promise發生異常,而沒有.catch()函數,也會在控制台拋出異常,但后面的代碼依舊會執行。