導讀
首先值得肯定的是在非同步程式碼組織中 async/await
確實起到了很棒的作用,書寫程式碼更加流暢。尤其是在作用域的處理上,讓非同步返回值和非同步函式呼叫時的作用域保持相同。
// es5
// 假設 bar 函式返回一個有效的 promise
function foo () {
return bar().then(res => {
console.log(res); // 1
})
console.log(res); // error
}
複製程式碼
// es7
// 假設 bar 函式返回一個有效的 promise
async function foo () {
let res = await bar();
console.log(res); // 1
}
複製程式碼
在相同的作用域下可以呼叫非同步返回值,這樣的程式碼閱讀起來更加符合直覺。
但在異常處理的時候,async/await
卻變得異常複雜,本文就講討論如何儘可能優雅的優化這個問題。
異常處理
所謂成也蕭何敗也蕭何,在 async/await
異常處理的時候需要引入 try/catch
來解決程式異常或者 reject
,但這又引入了一個子作用域干擾了程式碼的流暢性,更正:引入作用域的不是 try/catch
而是 let
。
我們來看一點程式碼,我將展示 try/catch
let
是如何隱式的建立了一個新的作用域。
// es7
try {
let a = true;
} catch (e) {
let a = false;
}
console.log(a);
// ⬇編譯後
// es5
"use strict";
try {
var _a = true; // 實際上 try catch 的花括號內是子作用域
} catch (e) {
var _a2 = false;
}
console.log(a); // error
複製程式碼
因為 try/catch
let
有隱式建立作用域的特性,這會讓在花括號中申明的變數無法被外部訪問到,這很容易讓程式碼容易出錯,並且書寫起來很不流暢。
下面就是應用了 try/catch
的 async/await
函式。
// es7
// 假設 bar 函式返回一個有效的 promise
async function foo () {
let res, err;
try {
res = await bar();
} catch (e) {
err = e;
}
if (err) {
return `error occur`;
}
return res;
}
複製程式碼
利用解構
既然 try/catch
的作用域令人頭疼,那麼我們也可以利用 es6
中解構的特性來優化一下程式碼。
// es7
// 假設 bar 函式返回一個有效的 promise
async function foo () {
let [err, res] = await to(bar());
if (err) {
return `error occur`;
}
return res;
}
function to (promise) {
return promise
.then(res => {
return [null, res];
})
.catch(err => {
return [err];
})
}
複製程式碼
函式 to
幫我們把 promise
按照一個標準的格式返回一個陣列,而這個陣列最終都會使 promise
進入 resolve
狀態,因此就可以避免使用 try/catch
結構。
如果在專案中,可以把函式 to
單獨封裝成一個模組使用。
// to.js
export default function to (promise) {
return promise
.then(res => {
return [null, res];
})
.catch(err => {
return [err];
})
}
複製程式碼
這篇文章是對 如何不用 try/catch 還能優雅使用 async/await (英文且需科學上網)這篇文章的實踐和解讀。
羅小黑寫寫文字
如果喜歡文章 請留下一個贊~
如果喜歡文章 分享給更多人~自由轉載-非商用-非衍生-保持署名(創意共享3.0許可證)
轉載時請保留原文連結 以保證可及時獲取對文章的訂正和修改