ECMAScript 之 Asynchronous
栏目: JavaScript · 发布时间: 7年前
内容简介:ECMAScript 對 Asynchronous 總共有 Promise、Generator 與 Async Await 三種支援,其中 Generator 屬於較進階的應用,主要是在寫 library,但 Promise 與 Async Await 則非常重要,寫 application 也很常用到。ECMAScript 2015 (Promise)ECMAScript 2017 (Async Await)
ECMAScript 對 Asynchronous 總共有 Promise、Generator 與 Async Await 三種支援,其中 Generator 屬於較進階的應用,主要是在寫 library,但 Promise 與 Async Await 則非常重要,寫 application 也很常用到。
Version
ECMAScript 2015 (Promise)
ECMAScript 2017 (Async Await)
API
productApi.js
import axios from 'axios';
import { API } from '../environment';
export default {
fetchProducts: () => axios.get(`${API}/products`),
};
實務上我們會將 API 部分另外寫在 api 目錄下,且另外寫 fetchXXX() method,但 axios.get() 回傳的到底是什麼型別呢?
是 ECMAScript 2015 新的 Promise 型別。
Promise
由於 Asynchronous 在所有 Synchronous 執行完才會執行,因此對於 AJAX 回傳的資料,對於 Synchronous 而言,屬於一種 未來值 。
也就是 AJAX 所回傳的資料,將來一定會有,但具體時間未知,只能先回傳 Promise 物件給你,一旦 AJAX 抓到資料,你就可以用 Promise 去換真實的資料。
就類似你去麥當勞買漢堡,錢都給了,但漢堡還沒做好,但未來一定會有,也是 未來值 ,因此店員會給你 取餐單 ,將來你可以用 取餐單 去換漢堡。
取餐單 就是 Promise。
mounted() {
const response = res =>
this.products = res.data;
const error = e =>
console.log(e);
const done = () =>
console.log('finally');
productApi
.fetchProducts()
.then(response)
.catch(error)
.finally(done);
},
fetchProducts() 會回傳 Promise 物件,該物件總共有 3 個 operator (也是 Higher Order Function)。
- then() :傳入要獲取 AJAX 資料的 function,當 AJAX 抓到資料後,會自己執行 function
- catch() :傳入若 AJAX 錯誤所執行的 function,當 AJAX 出錯時,會自己執行 function
- finally() :傳入 AJAX 最後所執行的 function,當 AJAX 執行完正,會自己執行 function
finally() 目前在 ECMAScript 定義為 stage 4,也就是即將 ECMAScript 正式定義,重要是 Babel 已經率先支援,因此可安心使用
Async Await
async mounted() {
try {
const response = await productApi.fetchProducts();
this.products = response.data;
} catch (err) {
console.log(err);
} finally {
console.log('finally');
}
},
Promise 屬於 FP 觀念下的產物 (也就是 Monad Pattern),若你習慣 Imperative 思維,也可以透過 Async Await 將 Asynchronous 寫的很 Synchronous。
將 function 前面宣告 async ,表示此為 Asynchronous Function,也就是內部將使用 await 。
response 為 productApi.fetchProducts() 所回傳的 Promise,是 未來值 , 觀念上 會 await 等 response 成真後才會繼續執行。
因為看起來很像 Synchronous 寫法,因此可以使用原本的 try catch finally 。
Async Await 只是程式碼看起來很像 Synchronous,但起本質仍然是 Asynchronous,因為 await 一定要對方回傳 Promise 才能使用,所以是百分之百的 Syntax Sugar Async Await 來自於 C# 5,在 ECMAScript 2017 正式定案,Babel 也完美支援
Why Promise ?
由 JavaScript 的 Event Loop Model 可知,有三種屬於 Asynchronous:
- DOM
- AJAX (XMLHttpRequest)
- setTimeout()
由於前端一定要使用 AJAX 呼叫 API,這屬於 Asynchronous 行為,會被安排在 Callback Queue ,等 Synchronous 執行完,最後才執行 Asynchronous。
在 ES5 之前,若 Asynchronous 之間有相依的先後關係,在 jQuery + Callback 只能這樣寫:
$.get('/products', (err, res) => {
if (err)
console.log(err);
else {
const product = ret.json();
$.get('/product/${ product[0].id}', (err, res) => {
if (err)
console.log(err);
else {
const item = res.json();
console.log(item);
}
});
}
});
這就是有名的 Callback Hell :
- 很容易寫出巢狀很深的 code 難以維護
- 每個 Callback 都要自己維護 Exception
fetch('/products')
.then(res => res.json())
.then(product => fetch('/products/${ prdouct[0].id}'))
.then(res => res.json())
.then(item => console.log(item));
.catch(e => console.log(e));
使用 Promise 後:
then()
Callback 雖然也能解決 Asynchronous,但會造成 Callback Hell,應盡量避免使用,且隨著 ECMAScript 2015 將 Promise 定為標準,越來越多 Library 直接回傳 Promise 型別 (Axios、Protractor …),且 Async Await 也是基於 Promise 技術,所以 Promise 已經成為不能不會的東西
Conclusion
語意
Sample Code
完整的範例可以在我的 GitHub 上找到
Reference
以上所述就是小编给大家介绍的《ECMAScript 之 Asynchronous》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。