Generator函數的異步應用

本系列屬於阮一峯老師所著的ECMAScript 6 入門學習筆記javascript


傳統方法

ES6以前,異步編程的方法,大概有下面四種:java

  • 回調函數
  • 事件監聽
  • 發佈/訂閱
  • Promise對象

Generator函數將JavaScript異步編程帶入了一個全新的階段es6

概念

傳統的編程語言,早有異步編程的解決方案,即多任務解決方案。其中一種叫"攜程"(coroutine),意思是多線程相互協做,完成異步任務編程

// yield命令成爲異步兩個階段的分界線,利用yield暫停任務,進行異步操做
function* asyncJob(){
  // ...其餘代碼
  var f= yield readFile(fileA)
  // ...其餘代碼
}
Generator函數的數據交換和錯誤處理

Generator函數能夠暫停執行和恢復執行,這是它能封裝異步任務的根本緣由。除此以外,它還有兩個特性能夠做爲異步編程的完美解決方案:函數體內外數據交換和錯誤處理機制多線程

// next返回值的value屬性,是Generator函數向外輸出的數據;next還能夠接收參數,向Generator函數體內輸入數據
function* gen(x){
  var y = yield x + 2
  return y
}
var g = gen(1)
g.next() // {value:3,done:false}
g.next(2) // {value:2,done:false}

// Generator函數內部能夠部署錯誤處理代碼,捕獲函數體外拋出的錯誤
function* gen(x){
  try{
    var y = yield x + 2
  }catch(e){
    console.log(e)
  }
  return y
}
var g = gen(1)
g.next()
g.throw('出錯了') // 出錯了
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
}
JavaScript語言的Thunk函數

JavaScript語言是傳值調用,它的Thunk函數含義有所不一樣。在JavaScript語言中,Thunk函數替換的不是表達式,而是多參數函數,將其替換成一個接受回調函數做爲參數的單參數函數async

// 正常多參數數版本函數
fs.readFile(fileName,callback)

// Thunk版本單參數函數
var Thunk = function(fileName){
  return function(callback){
    return fs.readFile(fileName,callback)
  }
}
var readFileThunk = Thunk(fileName)
readFileThunk(callback)

// 任何函數,只要參數又回調函數,就能寫成Thunk函數的形式
const Thunk = function(fn){
  return function(...args){
    return function(callback){
      return fn.call(this,...args,callback)
    }
  }
}
// 利用以上轉換器,生成f的Thunk函數
function f(a,cb){
  cb(a)
}
const ft = Thunk(f)
ft(1)(console.log) // 1
Generator函數的流程管理

Thunk函數如今能夠用於Generator函數的自動流程管理。但Thunk函數並非Generator函數自動執行的惟一方案。由於自動執行的關鍵是,必須有一種機制,自動控制Generator函數的流程,接收和交還程序的執行權。回調函數能夠作到,Promise對象也能夠作到編程語言

function run(fn){
  var gen = fn()
  function next(err,data){
    var result = gen.next(data)
    if(result.done) return
    result.value(next)
  }
  next()
}

function* g(){
  // ...
}
// run函數是一個Generator函數的自動執行器,next函數是Thunk的回調函數,result.value就是Thunk函數
run(g)
相關文章
相關標籤/搜索