假設代碼塊執行拋出錯誤 fail,那麼捕獲該錯誤的寫法爲:異步
try { // 代碼塊執行,並拋出 fail 錯誤 throw new Error('fail'); } catch (e) { console.log(e); }
咱們先來針對上面的代碼改寫一下,加入一個定時器。async
try { setTimeout(()=>{ throw new Error('fail'); // Uncaught Error: fail }, 1000); } catch (e) { console.log(e); }
像這樣,將 try/catch 扔在定時器的外面,是沒法捕獲到內部的錯誤的。函數
正確的作法應該是:code
setTimeout(()=>{ try{ throw new Error('fail'); } catch (e) { console.log(e); } },1000);
function doSomething() { return new Promise((resolve, reject) => { // 同步代碼中的 throw 能夠被捕捉到 throw new Error('fail'); }); } doSomething() .then((x) => { console.log('success:', x); }) .catch((err) => { console.log('fail:', err); });
這樣寫是沒有問題的,錯誤可以被捕獲到。但只要稍微修改一下,可能就出現問題了。好比:同步
function doSomething() { return new Promise((resolve, reject) => { // 異步代碼中的 throw 不能被 Promise 的 catch 捕捉到 setTimeout(() => { throw new Error("fail"); }, 1000); }); } doSomething() .then((x) => { console.log('success:', x); }) .catch((err) => { console.log('fail:', err); });
這裏拋出但錯誤將不能被捕獲。因此,在 Promise 中,咱們通常經過 reject 來拋出錯誤。it
function doSomething(x) { return new Promise((resolve, reject) => reject(x)); } doSomething('fail').then((x) => { console.log('success:', x); }).catch((err) => { console.log('fail:', err); }); // fail: fail
另外,還有一個比較有意思的細節,在 catch 以後繼續添加 .then 會被繼續執行。io
function doSomething(x) { return new Promise((resolve, reject) => reject(x)); } doSomething('fail').then((x) => { console.log('success:', x); }).catch((err) => { console.log('fail:', err); // 這裏能夠寫 return 給下面的方法繼續執行 }).then((x) => { console.log('continue:', x); }); // fail: fail // continue: undefined
本質上來說, Async/Await 是經過 Promise 實現,因此基本跟上面 Promise 所講的差很少。console
能夠在 await 方法外嵌套 try/catch,相似這樣:function
function doSomething(x) { return new Promise((resolve, reject) => reject(x)); } (async () => { try { const result = await doSomething('fail'); console.log('success:', result); // return 返回 } catch (err) { console.log('fail:', err); // return 返回 } })(); // fail: fail
但這裏就有一個問題,好比函數須要有返回,那麼返回的語句就須要寫兩次,正常但時候返回結果,錯誤的時候,返回一個 throw new Error()
或者其餘的。有一個小的竅門,能夠這樣寫:class
function doSomething(x) { return new Promise((resolve, reject) => reject(x)); } (async () => { const result = await doSomething('fail').catch((err) => { console.log('fail:', err); return 0; // 默認值 }); console.log('success:', result); })(); // fail: fail // success: 0
在錯誤捕獲到以後,從新分配一個默認值,讓代碼繼續運行。