ES6提供了異步編程的幾個新特性:
本篇主要參考阮一峰大神的ES6文章蛔琅。
Promise
1.基本用法:
var promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 異步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
Promise構(gòu)造函數(shù)接受一個函數(shù),該函數(shù)的變量為resolve和reject威酒,分別為兩個函數(shù)游两,作用為:resolve將promise對象的狀態(tài)變?yōu)閞esolved,reject將promise對象的狀態(tài)變?yōu)閞ejected糯景。
Promise對象創(chuàng)建即執(zhí)行:
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('Resolved.');
});
console.log('Hi!');
// Promise
// Hi!
// Resolved
2.Promise.prototype.then()方法
生成Promise對象后可通過then()方法來指定resolved、rejected狀態(tài)下的回調(diào)函數(shù)省骂。
promise.then(function(value) {
// success
}, function(error) {
// failure
});
2.Promise.prototype.catch()方法
是.then(null, rejection)的別名蟀淮,用于指定發(fā)生錯誤時的回調(diào)函數(shù)。
用于獲取promise rejected狀態(tài)下的回調(diào)或者拋出異常钞澳。
Promise對象的錯誤狀態(tài)會一直向后傳遞直到被catch怠惶,但并不會被全局捕獲。
3.Promise.all()
用于將多個Promise實例轧粟,包裝成一個新的Promise實例策治。
var p = Promise.all([p1, p2, p3]);
- 只有p1、p2兰吟、p3的狀態(tài)都變成fulfilled通惫,p的狀態(tài)才會變成fulfilled,此時p1揽祥、p2讽膏、p3的返回值組成一個數(shù)組,傳遞給p的回調(diào)函數(shù)拄丰。
- 只要p1、p2俐末、p3之中有一個被rejected料按,p的狀態(tài)就變成rejected,此時第一個被reject的實例的返回值卓箫,會傳遞給p的回調(diào)函數(shù)载矿。
4.Promise.race()
同樣是將多個Promise實例,包裝成一個新的Promise實例。
var p = Promise.race([p1, p2, p3]);
只要p1闷盔、p2弯洗、p3之中有一個實例率先改變狀態(tài),p的狀態(tài)就跟著改變逢勾。那個率先改變的 Promise 實例的返回值牡整,就傳遞給p的回調(diào)函數(shù)。
5.Promise.resolve()
將一個對象轉(zhuǎn)為Promise對象
6.Promise.reject()
將一個對象轉(zhuǎn)為Promise對象溺拱,狀態(tài)是rejected
Generator
generator函數(shù)類似于狀態(tài)機(jī)
1.基本用法
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
2.yield語句
調(diào)用generator函數(shù)逃贝,并不會立即執(zhí)行,而必須要調(diào)用next方法迫摔,執(zhí)行到generator函數(shù)中的yield語句后返回沐扳。
yield語句后的表達(dá)式作為函數(shù)返回值。
function* f() {
console.log('執(zhí)行了句占!')
}
var generator = f();
setTimeout(function () {
generator.next()
}, 2000);
3.return方法
可以返回給定的值沪摄,并且終結(jié)遍歷Generator函數(shù)。
4.Generator函數(shù)與異步編程
可采用co模塊纱烘、thunk函數(shù)自動執(zhí)行
ES7的async函數(shù)
就是 Generator 函數(shù)的語法糖
如Generator寫法:
var fs = require('fs');
var readFile = function (fileName) {
return new Promise(function (resolve, reject) {
fs.readFile(fileName, function(error, data) {
if (error) reject(error);
resolve(data);
});
});
};
var gen = function* () {
var f1 = yield readFile('/etc/fstab');
var f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
寫成async函數(shù)卓起,就是下面:
var asyncReadFile = async function () {
var f1 = await readFile('/etc/fstab');
var f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
比較發(fā)現(xiàn),async函數(shù)就是將 Generator 函數(shù)的星號(*)替換成async凹炸,將yield替換成await戏阅,僅此而已。
async函數(shù)對 Generator 函數(shù)的改進(jìn)啤它,體現(xiàn)在以下四點:
- 內(nèi)置執(zhí)行器
Generator 函數(shù)的執(zhí)行必須靠執(zhí)行器奕筐,所以才有了co模塊,而async函數(shù)自帶執(zhí)行器变骡。也就是說离赫,async函數(shù)的執(zhí)行,與普通函數(shù)一模一樣塌碌,只要一行渊胸。 - 更好的語義
async和await,比起*和yield台妆,語義更清楚翎猛。async表示函數(shù)里有異步操作,await表示緊跟在后面的表達(dá)式需要等待結(jié)果接剩。 - 更廣的適用性
co模塊約定切厘,yield命令后面只能是 Thunk 函數(shù)或 Promise 對象,而async函數(shù)的await命令后面懊缺,可以是Promise 對象和原始類型的值(數(shù)值疫稿、字符串和布爾值,但這時等同于同步操作)。 - 返回值是 Promise
async函數(shù)的返回值是 Promise 對象遗座,這比 Generator 函數(shù)的返回值是 Iterator 對象方便多了舀凛。你可以用then方法指定下一步的操作。