摘要:概念生成器是由生成器函數運行后得到的,是可迭代的。關鍵字使生成器函數執行暫停,關鍵字后面的表達式的值返回給生成器的調用者。模擬異步請求返回一個隨機數演示地址不過,自從出了和之后,更多的是用這個組合,其使用也更簡單,范圍也更廣。
概念
生成器是由生成器函數( generator function )運行后得到的,是可迭代的。
function* gen() { yield "a"; yield "b"; yield "c"; } let g = gen(); // "Generator { }"原理及簡單運用
生成器有一個很大的特點,它可以暫停內部代碼運行,返回一個值給外部函數。(暫停后不會阻止其他代碼運行)當外部調用其 next 方法后,會繼續執行剩下的代碼,并接受外部傳來的一個參數。這個實現主要依賴于關鍵字 yield 。
yield 關鍵字使生成器函數執行暫停,yield 關鍵字后面的表達式的值返回給生成器的調用者。它可以被認為是一個基于生成器的版本的 return 關鍵字。
function* g(){ var a = yield 2; console.log(a); } var it = g(); // 返回一個可迭代的生成器對象 console.log(it.next()); // 執行生成器函數內部代碼,第一次返回 {done: false, value: 2} it.next(3); // 繼續執行生成器函數內部代碼,同時向生成器傳遞參數3,最后返回 {done: true, value: undefined}
一個簡單的計數器
function* count(){ var n = 1; while(true){ yield n++; } } var it = count(); it.next(); // 1 it.next(); // 2 it.next(); // 3用同步方式寫異步代碼
以前處理異步 ajax 請求結果,一般采用傳遞回調函數的方式。一旦遇到多層回調嵌套,代碼的可讀性會降低,并且調試起來也不方便。有了生成器之后,我們就可以用同步的方式寫異步的代碼。這聽上去非常的有意思。我們的代碼將會是這樣的
function foo(){ var result = asyncFun(); // asyncFun 是異步函數,result 是異步返回的結果 console.log(result); }
當然,上面的代碼并不能得到正確的結果,它只是一個設想。我們正打算用生成器來實現,而且這是可行的。想想生成器有哪些特點:
它能暫停,向外部返回值
能繼續執行剩下的代碼,并接受外部傳來的參數
這就足夠了。有了生成器函數,現在我們重新來設計代碼:
function* foo(){ // 這里遇到了異步方法,必須停下來。 // 等待異步方法執行完畢,并返回結果,繼續運行代碼。當然,同步 ajax 不能算,它不是異步 // 輸出結果 }
靜下來想一想有哪些關鍵字,與暫停、繼續有關。停下來...繼續...停下來...繼續...停下來...繼續...Don"t...Stop...Don"t...Stop...Don"t...Stop......這兩個詞就是 yield、next.
function *foo(){ var result = yield asyncFun(next); console.log(result); }
當代碼遇到 yield 會暫停,這個時候 asyncFun 函數是不會暫停的,會執行,等執行完畢,再調用生成器的 next 方法,并將返回結果作為參數傳給 next。由于在生成器函數內部我們拿不到 next,必須借助于全局變量來傳遞 next。
var next, gn; function asyncFun(next){ // 模擬異步請求 setTimeout(function(){ // 返回一個隨機數 next(Math.random()) }, 1000) } function* foo(){ var result = yield asyncFun(next); console.log(result); } gn = foo(); next = gn.next.bind(gn); next(); // 打印隨機數
這樣寫,運行看上去有些繁重。可以寫一個包裝函數運行含有異步代碼的生成器函數。
function asyncFun(next){ // 模擬異步請求 setTimeout(function(){ // 返回一個隨機數 next(Math.random()) }, 1000) } function* foo(){ var result = yield function(next){asyncFun(next)}; console.log(result); } function wrapFun (gFn){ var gn = foo(), next = gn.next.bind(gn); next().value(next); } wrapFun(foo);
演示地址
不過,自從出了 Promise 和 await 之后,更多的是用這個組合,其使用也更簡單,范圍也更廣。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102619.html
摘要:所以,打包工具就出現了,它可以幫助做這些繁瑣的工作。打包工具介紹僅介紹款主流的打包工具,,,,以發布時間為順序。它定位是模塊打包器,而屬于構建工具。而且在其他的打包工具在處理非網頁文件比如等基本還是需要借助它來實現。 本文當時寫在本地,發現換電腦很不是方便,在這里記錄下。 前端的打包工具 打包工具可以更好的管理html,css,javascript,使用可以錦上添花,不使用也沒關系...
摘要:我們還能如何使用生成器作為迭代器的能力使對象可迭代。一些重要的事件值得了解生成器是由布倫丹艾希首次在上實現的。布倫丹艾希的設計是緊緊跟隨由啟發的生成器。 什么是生成器? 我們先從下面的這里例子開始。 function* quips(name) { yield hello + name + !; yield i hope you are enjoying the blog po...
摘要:三集成所需要的依賴和在或加載模塊時,對代碼進行預處理,語法轉化為語法。到目前位置,用于開發應用的環境已經配置好了。 本系列主要學習webpack的配置。webpack自己間接的用過不少次,但是自己配置卻沒多少次,所以特地寫寫文章,學習webpack的配置,有不恰當的地方,歡迎指正。這次配置 babel 。 若你對webpack的概念還不了解,先查看相應文檔webpack中文文檔 一、初...
摘要:年月,的創造者公司,決定將提交給國際標準化組織,希望這種語言能夠成為國際標準。這表示外層代碼塊不受內層代碼塊的影響。也可以運用于函數及其他文中就簡單介紹這么多,想更加了解新特性的可以自尋查看一下阮一峰的一本入門 ES6新特性 最近在項目中遇到了很多ES6的語法,遇到了不少坑坑洼洼,因此,在這里就簡單介紹一下ES6中的一些新特性 如果想真正的了解ES6和ES5有什么不同,這里推薦看一下...
閱讀 1325·2021-11-11 11:00
閱讀 3041·2021-09-24 09:47
閱讀 4951·2021-09-22 15:53
閱讀 960·2021-09-10 10:50
閱讀 3207·2021-09-01 11:40
閱讀 1160·2019-08-30 15:55
閱讀 473·2019-08-30 12:49
閱讀 1049·2019-08-29 17:12