ES6 async/await在專案中的應用
最近在專案中有這麼一個需求,當用戶使用積分去兌換某個商品之後,點選某個按鈕會呼叫兩個介面,其中先呼叫一個介面,從介面中獲取record_id之後,再呼叫另外一個介面,將獲得的record_id傳遞到第二個介面中,然後從第二個介面返回goods_name,那麼我們來看一下用以前的方式和使用ES6的async/await方式來編寫的不同。
一開始,我使用的方式如下
apis.postExchangeGoods({},{goods_id: this.current_goods.id})
.then(res => {
if (res.data.errcode === 0) {
let record_id = res.data.record_id;
apis.postUserInfo({},{record_id: record_id})
.then(res => {
this.show = false;
let goods_name = res.data.goods_name;
this.$router.push({
name: 'xxx'
});
});
});
}
});
可以看到這種方式下,在一個介面的回撥中呼叫另一個介面,程式碼不僅多,看起來也比較雜亂,而且此時只是呼叫2個介面,如果在某些需求下我們要呼叫四五個介面甚至十個介面,那麼此時程式碼不僅看起來特別亂,而且會各種回撥介面的巢狀,維護起來也不方便,掉入傳說中的callback hell。而es6中推出async/await函式就可以解決這種問題,我們來看一下使用這種方式後寫出來的程式碼:
1.async function postUserInfo() {
2. try {
3. var result1 = await window.apis.postExchangeGoods({}, {goods_id: _this.goods_id});
4. var result2 = await window.apis.postUserInfo({},{record_id:resul1.data.rescord_id});
5. return result2.data.goods_name;
6. } catch(e) {
7. console.log(e);
8. }
9.}
10.postUserInfo().then((goods_name) => {
11. this.$router.push({
12. name: 'xxx'
13. });
14.});
第二種寫法需要使用async function去定義一個方法,那麼這個方法最後會返回一個Promise物件。
在這個方法中呼叫那兩個介面,第3行程式碼中使用了await命令,那麼此時該方法會等待第3行的非同步操作執行完畢之後,才會繼續執行下面的程式碼,如果由於網路問題該postExchangeGoods請求了5秒,那麼程式碼就會在這裡等待5秒,直到獲取返回結果,然後再執行下面的程式碼。
當async方法裡面的內容全部執行完畢之後,就會呼叫第10行中的then指定的回撥方法。
需要注意的是:await後面跟著的函式,必須通過Promise.resolve或者Promise.reject來返回某些內容
我們對比一下這兩種寫法,可以看得出,第二種方法首先程式碼比較簡潔,呼叫兩個介面只寫了第3行和第4行程式碼,然後用一個變數來獲取返回的結果。而且更重要的是,他脫離了第一種寫法的那種幾個回撥函式巢狀的現象,程式碼變得更清晰,維護起來也更好。當然,由於async/await是es6中推出的API,使用babel並不能將其轉譯為大部分瀏覽器支援的ES5,此時我們需要使用墊片。