ECMAScript 6-Generator函式的非同步應用
阿新 • • 發佈:2020-09-01
協程
多個執行緒互相協作,完成非同步任務。yield命令表示執行到此處,執行權將交給其他協程,也就是說,yield命令是非同步兩個階段的分界線。協程遇到yield命令就暫停,等到執行權返回,再從暫停的地方繼續往後執行。
function *asyncJob() {
// ...其他程式碼
var f = yield readFile(fileA);
// ...其他程式碼
}
Generator 函式實現協程
function* gen(x) { var y = yield x + 2; return y; } var g = gen(1); //返回一個遍歷器物件 不返回結果 //指向yield並執行,value是後面表示式的值。next方法的作用是分階段執行Generator函式 g.next() // { value: 3, done: false } g.next() // { value: undefined, done: true }
Generator 函式的資料交換和錯誤處理
-
next接受引數進行資料交換
next返回值的value屬性,是 Generator 函式向外輸出資料;next方法還可以接受引數,向 Generator 函式體內輸入資料。next接受的引數會被當做上一個yield的返回結果function* gen(x) { var y = yield x + 2; return y; } var g = gen(1); g.next() // { value: 3, done: false } g.next(2) // { value: undefined, done: true } //在這裡傳入的2會被當做是上一個yield的返回結果,即yield x+2等於2,這個時候y=2並返回
-
錯誤處理
Generator 函式體外,使用指標物件的
throw
方法丟擲的錯誤,可以被函式體內的try...catch
程式碼塊捕獲function* gen(x){ try { var y = yield x + 2; } catch (e){ console.log(e); } return y; } var g = gen(1); g.next(); g.throw('出錯了'); // 出錯了
非同步任務的封裝
var fetch = require('node-fetch'); function* gen(){ var url = 'https://api.github.com/users/github'; var result = yield fetch(url); //fetch讀取介面,返回一個 Promise 物件 console.log(result.bio); } var g = gen(); var result = g.next(); //執行fetch(url),返回具有value和done屬性的result物件 //在這裡value相當於fetch返回的Promise物件,data就是介面返回的結果 result.value.then(function(data){ return data.json(); }).then(function(data){ g.next(data); });
Thunk 函式
背景:函式引數的求值策略
var x = 1;
function f(m){
return m * 2;
}
f(x + 5)
//1. 傳值呼叫
在進入函式體前就先計算x+5,成f(6),6再傳進去執行,即6*2
//2. 傳名呼叫
直接將表示式x+5傳入,即(x+5)*2
Thunk 函式的含義
Thunk 函式是自動執行 Generator 函式的一種方法。編譯器的“傳名呼叫”實現,往往是將引數放到一個臨時函式之中,再將這個臨時函式傳入函式體。這個臨時函式就叫做 Thunk 函式
function f(m) {
return m * 2;
}
f(x + 5);
// 等同於
var thunk = function () {
return x + 5;
};//相當於引數被替換成一個函式
function f(thunk) {
return thunk() * 2;
}
任何函式,只要引數有回撥函式,就能寫成 Thunk 函式的形式。下面是一個簡單的 Thunk 函式轉換器
function f(a, cb) {
cb(a);
}
let ft = Thunk(f); //轉交給Thunk暫存
let log = console.log.bind(console); //會作為表示式放進去而不會立即執行
ft(1)(log) // 1
Thunkify 模組
生產環境的轉換器,建議使用 Thunkify 模組。首先安裝模組
$ npm install thunkify
使用
var thunkify = require('thunkify');
var fs = require('fs');
var read = thunkify(fs.readFile);
read('package.json')(function(err, str){
// ...
});
co模組
用於 Generator 函式的自動執行,
這個 Generator 函式用於依次讀取兩個檔案
var gen = function* () {
var f1 = yield readFile('/etc/fstab');
var f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
co 模組可以讓你不用編寫 Generator 函式的執行器
var co = require('co');
co(gen);
co
函式返回一個Promise
物件,因此可以用then
方法添加回調函式
co(gen).then(function (){
console.log('Generator 函式執行完成');
});