摘要:道理大概就是,有兩個異步程序,用小明和小紅指代它們。小紅需要等小明執行完了才可以被執行,那么我們在執行到小明時,暫停程序的運行通過,等到小明有了返回結果時,再執行后面跟著的小紅。在最新的中,已經拋棄了,轉而使用。
ES6中Generator
Generator是ES6一個很有意思的特性,也是不容易理解的特性。不同于let/const提供了塊級作用域這樣明顯的目的,這玩意兒被搞出來到底是干嘛的?
首先我們需要明確一個問題,在JavaScript中,任何一個函數只要開始執行,便無法停止下來直到執行完成(別跟我提debug,你見過哪個用戶在使用產品的還得開個debug調試你的代碼)。
but,Generator提供這種能力。 看下面代碼:
function *g(){ console.log("start"); yield 1; console.log("middle"); yield 2; console.log("end"); } var g1 = g(); console.log(g1.next()); // start // {value: 1, done: false} console.log(g1.next()); // middle // {value: 2, done: false} console.log(g1.next()); // end // {value: undefined, done: true}
根據輸出結果,我們看到,在函數g中,碰到yield關鍵詞,運行的程序會停下來。只有調用 next()方法,才會繼續執行函數g中的代碼。所以函數g本身有暫停狀態。
至此,我們需要知道:
Generator不是函數,不是函數,不是函數;
g()不會立即出發執行,而是一上來就暫停,并返回一個Iterator對象;
每次g1.next()都會打破暫停狀態去執行,直到遇到下一個yield或者return
遇到yield時,會執行yeild后面的表達式,并返回執行之后的值,然后再次進入暫停狀態,此時done: false。
遇到return時,會返回值,執行結束,即done: true
每次g.next()的返回值永遠都是{value: ... , done: ...}的形式
Generator與異步既然Generator可以函數停下來,有些腦洞清奇的人,想到了可不可以用Generator處理異步程序。
先看一個傳統例子:
function asyn(fn) { return new Promise((resolve,reject)=>{ setTimeout(()=>{ fn(); resolve(true); }, 1000); }); } function main() { console.log("start"); asyn(function(d) { console.log("async one"); asyn(function(d) { console.log("async two"); console.log("end"); }); }); } main();
再來看看使用了Generator的異步程序:
function asyn(fn) { return new Promise((resolve,reject)=>{ setTimeout(()=>{ fn(); resolve(true); }, 1000); }); } co(function*() { console.log("start"); yield asyn(function(d) { console.log("async one"); }); yield asyn(function(d) { console.log("async two"); }); console.log("end"); }); function co(fn) { return new Promise((resolve,reject)=>{ let g = fn(); onFullfilled(); function onFullfilled() { let ret = null; ret = g.next(); next(ret); } function next(ret) { if(ret.done) return resolve(ret.value); ret.value.then(onFullfilled); } } ); }
函數在異步程序沒有采用嵌套回調,是直接用同步的方式寫了出來。道理大概就是,有兩個異步程序,用小明和小紅指代它們。小紅需要等小明執行完了才可以被執行,那么我們在執行到小明時,暫停程序的運行(通過yield),等到小明有了返回結果時,再執行后面跟著的小紅(next())。
在上面的程序中,我們添加了一個co函數,這個函數的作用是讓Generator自動執行下去。直白來說,就是當第一個異步函數返回后,自動調用next()方法運行后面的代碼。
Generator與KoaKoa是基于Node.js的Web應用框架。在Koa中,處理的異步程序主要是網絡請求(HTTP)、文件讀取和數據查詢。這里面的異步場景較多,如果再加上程序分層,采用傳統的callback方式,那回調多了去了。
app.on("get", function(){ auth(function(){ router(function(){ find(function(){ save(function(){ render(function(){ //...... }) }) }) }) }) })
這樣寫法對于程序維護及其不利,毫無便捷性可言。在有了generator后,我們便可以像上面那種方式來寫程序。Koa最初的版本就是通過這種方式,讓中間處理程序都轉成一個個"yield"(中間件)。通過中間件的形式去處理客戶端請求,讓開發App應用更加靈活,不受框架自身限制。
在最新的Koa2中,已經拋棄了Genetator,轉而使用async/await。
但是無論采用哪種方式,其本質都是利用了Promise。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/98413.html
摘要:調用函數后和普通函數不同的是,該函數并不立即執行,也不返回函數執行結果,而是返回一個指向內部狀態的對象,也可以看作是一個遍歷器對象。第一個只是用來啟動函數內部的遍歷器,傳參也沒有多大意義。 之前斷斷續續接觸到了一些ES6的知識,異步編程方面聽得比較多的就是Promise,直到最近比較系統地學習了ES6的新特性才發現Generator這個神奇的存在,它可以實現一些前所未有的事情,讓我頓時...
摘要:同時,迭代器有一個方法來向函數中暫停處拋出一個錯誤,該錯誤依然可以通過函數內部的模塊進行捕獲處理。 本文翻譯自:Diving Deeper With ES6 Generators 由于個人能力有限,翻譯中難免有紕漏和錯誤,望不吝指正issue ES6 Generators:完整系列 The Basics Of ES6 Generators Diving Deeper With E...
摘要:關于協程和中的什么是協程進程和線程眾所周知,進程和線程都是一個時間段的描述,是工作時間段的描述,不過是顆粒大小不同,進程是資源分配的最小單位,線程是調度的最小單位。子程序就是協程的一種特例。 關于協程和 ES6 中的 Generator 什么是協程? 進程和線程 眾所周知,進程和線程都是一個時間段的描述,是CPU工作時間段的描述,不過是顆粒大小不同,進程是 CPU 資源分配的最小單位,...
摘要:示例運行函數彈出彈出函數接收參數,返回值。其中,返回一個對象,是的返回值,代表函數是否執行完成。 ES6特性介紹(下) ES6新的標準,新的語法特征:1、變量/賦值2、函數3、數組/json4、字符串5、面向對象6、Promise7、generator8、ES7:async/await 《【Web全棧課程二】ES6特性介紹(上)》見:https://segmentfault.com/a...
摘要:前言本文就是簡單介紹下語法編譯后的代碼。如果有錯誤或者不嚴謹的地方,請務必給予指正,十分感謝。如果喜歡或者有所啟發,歡迎,對作者也是一種鼓勵。 前言 本文就是簡單介紹下 Generator 語法編譯后的代碼。 Generator function* helloWorldGenerator() { yield hello; yield world; return ending...
閱讀 629·2023-04-26 01:53
閱讀 2753·2021-11-17 17:00
閱讀 2889·2021-09-04 16:40
閱讀 1988·2021-09-02 15:41
閱讀 838·2019-08-26 11:34
閱讀 1227·2019-08-26 10:16
閱讀 1338·2019-08-23 17:51
閱讀 823·2019-08-23 16:50