ECMAScript 6(ES6) 特性概覽和與ES5的比較14(下)-生成器Generators

十四.Generator生成器

4.生成器控制流

支持生成器,迭代器的特殊情況,其中控制流可以暫停和恢復,以便支持與“協同例程”結合Promise的異步編程(見下文)。 [注意:通用異步函數通常由可重用的庫提供,這裏只是爲了更好地理解。 在實踐中見co或Bluebird的協程。]

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

協程有點像函數,又有點像線程。它的運行流程大致如下。
第一步,協程A開始執行。
第二步,協程A執行到一半,進入暫停,執行權轉移到協程B。
第三步,(一段時間後)協程B交還執行權。
第四步,協程A恢復執行。
上面流程的協程A,就是異步任務,因爲它分成兩段(或多段)執行。
舉例來說,讀取文件的協程寫法如下。

function* asyncJob() {
  // ...其他代碼
  var f = yield readFile(fileA);
  // ...其他代碼
}

上面代碼的函數asyncJob是一個協程,它的奧妙就在其中的yield命令。它表示執行到此處,執行權將交給其他協程。也就是說,yield命令是異步兩個階段的分界線。

協程遇到yield命令就暫停,等到執行權返回,再從暫停的地方繼續往後執行。它的最大優點,就是代碼的寫法非常像同步操作,如果去除yield命令,簡直一模一樣。
—摘自ECMAScript 6 入門 阮一峯

ECMAScript 6

//通用異步控制流驅動程序
function async (proc, ...params) {
    let iterator = proc(...params)
    return new Promise((resolve, reject) => {
        let loop = (value) => {
            let result
            try {
                result = iterator.next(value)
            }
            catch (err) {
                reject(err)
            }
            if (result.done)
                resovle(result.value)
            else if ( typeof result.value === "object" && 
                      typeof result.value.then === "function")
                result.value.then((value) => {
                    loop()
                },(err) => {
                    reject(err)
                })
            else
                loop(result.value)
        }
        loop()
    })
}

//特定的應用程序異步構建
function makeAsync (text, after) {
    return new Promise((resolve, reject) =>{
        setTimeout(() => resolve(text),after)
    })
}

//特定的應用程序異步過程
async(function* (greeting) {
   let foo = yield makeAsync("foo", 300)
   let bar = yield makeAsync("bar", 200)
   let baz = yield makeAsync("bar", 100)
   return `${greeting} ${foo} ${bar} ${baz}`
},"Hello").then((msg) => {
    console.log("RESULT:", msg) //"Hello foo bar baz"
})

ECMAScript 5

//ES5中沒有響應的表達方式

5.生成器方法

基於生成器函數支持生成器方法,即類和對象中的方法。

ECMAScript 6

class Clz {
    * bar () {
        ...
    }
}
let Obj = {
    * foo () {
        ...
    }
}

ECMAScript 5

//ES5中沒有響應的表達方式
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章