摘要:序在中,大家討論的最多的就是異步編程的操作,如何避免回調的多次嵌套。今天所講的和就是和異步編程有關,可以幫助我們把異步編程同步化。然而這樣的方法依然需要依賴外在的庫函數,于是中提出了和關鍵字。
序
在Javascript中,大家討論的最多的就是異步編程的操作,如何避免回調的多次嵌套。異步操作的回調一旦嵌套很多,不僅代碼會變的臃腫,還很容易出錯。各種各樣的異步編程解決方案也被不斷提出,例如大家所熟知的Promise,co等等。今天所講的Generator和yield就是和異步編程有關,可以幫助我們把異步編程同步化。
Generator簡介Generator在形式上和函數差不多,只是在function和函數名之間多了一個*。Generator內部必須使用yield關鍵字。例如:
function * gen(){ var result1 = yield "hello"; var result2 = yield "world"; return result1 + result2; }
當調用Generator函數時,并不會執行函數內部的代碼,而是返回一個遍歷器,該遍歷器包含一個next方法。每次執行next方法,Generator函數體會開始執行,直到遇到yield語句,執行該語句并在此暫停。用法如下:
var g = gen(); g.next(1); //{value : "hello", done : false} g.next(2); //{value : "world", done : false} g.next(); //{value : 3, done: true} g.next(); //{value : undefined, done: true}
調用next方法會返回一個對象,這個對象包含兩個屬性,value和done,value即是當前yield語句的值。done表示Generator函數體是否被執行完。next方法同時接受一個參數,這個參數會作為yield語句的返回值,可以被后面的程序所使用。當程序執行完或者遇到return語句,value即為函數體的返回值,done就變成了true。至此,如果再執行next方法,value就為undefined, done依然是true。
Generator在遍歷中的應用在js中,我們要遍歷一個數組,我們可以用for...of這樣的語句來進行遍歷,這其實也是因為數組中包含了一個Generator遍歷器。如果我們的自己定義的對象也包含一個遍歷器,我們也就可以通過for...of等遍歷語句來遍歷自定義的對象。這個遍歷器被存在Symbol.iterator屬性中。
var myArray = { 0: "你", 1: "的", 2: "名字", length: 3 }; myArray[Symbol.iterator] = function * (){ for(var i = 0; i < this.length; i++) { yield this[i]; } }; for(var item of myArray) { console.log(item); } //你 //的 //名字Generator在異步編程中的應用
Javascript的核心就是異步編程,每個異步操作都會提供一個callback回調函數來返回執行的結果。假設我們有幾個操作,后一個操作依賴前一個操作的結果,如果采用回調的方式:
step1(function(value1) { step2(value1, function(value2) { step3(value2, function(value3)) { //some code } }); })
這樣的代碼一單回調的嵌套變多,會讓程序變的非常難理解,同時也很容易出錯。我們要做的就是將回調變的扁平化。Promise對象就是這樣的功能,將上述的操作Promise化:
step1().then(function(value1){ return step2(value1); }).then(function(value2){ return step3(value2); }).then(function(){ //some code })
我們可以看到嵌套變少了,但是這并不是最理想的解決方案,如果我們能將異步操作變成同步操作那樣,即沒了嵌套,程序也會變的好理解。Generator函數就給我們提供的這樣的機會。
function *workflow(){ var value1 = yield step1(); var value2 = yield step2(); var value3 = yield step3(); //some code }
這樣就是我們希望結果,異步編程編程了同步編程的形式。我們接下來要做的是讓這個Generator執行起來,所以我們需要一個執行器。co就是一個執行器,讓Generator自動執行。
co(function *workflow(){ var value1 = yield step1(); var value2 = yield step2(); var value3 = yield step3(); //some code });
co有個限制,yield語句后面跟的只能是Promise對象或者Thunk函數,關于co更詳細的介紹,可以參考阮老師的文章co 函數庫的含義和用法。然而這樣的方法依然需要依賴外在的庫函數,于是ES6中提出了async和await關鍵字。async和await其實就是Generator的語法糖。只是它自帶執行器。將上面的代碼改寫成async形式:
async function workflow(){ var value1 = await step1(); var value2 = await step2(); var value3 = await step3(); //some code } var result = workflow();
async沒有了co的限制。await關鍵字后面可以跟 Promise 對象和原始類型的值(數值、字符串和布爾值,但這時等同于同步操作)。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88031.html
摘要:從開始,就在引入新功能,來幫助更簡單的方法來處理異步編程,幫助我們遠離回調地獄。而則是為了更簡潔的使用而提出的語法,相比這種的實現方式,更為專注,生來就是為了處理異步編程。 從Promise開始,JavaScript就在引入新功能,來幫助更簡單的方法來處理異步編程,幫助我們遠離回調地獄。 Promise是下邊要講的Generator/yield與async/await的基礎,希望你已...
摘要:以下展示它是如何工作的函數使用構造函數創建一個新的對象,并立即將其返回給調用者。在傳遞給構造函數的函數中,我們確保傳遞給,這是一個特殊的回調函數。 本系列文章為《Node.js Design Patterns Second Edition》的原文翻譯和讀書筆記,在GitHub連載更新,同步翻譯版鏈接。 歡迎關注我的專欄,之后的博文將在專欄同步: Encounter的掘金專欄 知乎專欄...
摘要:返回的遍歷器對象,可以依次遍歷函數內部的每一個狀態。下一步,必須調用遍歷器對象的方法,使得指針移向下一個狀態。從語義上講,第一個方法用來啟動遍歷器對象,所以不用帶有參數。 Generator理解 Generator 函數是 ES6 提供的一種異步編程解決方案,可以這么理解: 從語法上,首先可以把它理解成,Generator 函數是一個狀態機,封裝了多個內部狀態。執行 Generato...
摘要:而在中是迭代器生成器,被創造性的拿來做異步流程控制了。當執行的時候,并不執行函數體,而是返回一個迭代器。行代碼再看看文章開頭的行代碼首先生成一個迭代器,然后執行一遍,得到的是一個對象,里面再執行。 廣告招人:阿里巴巴招前端,在這里你可以享受大公司的福利和技術體系,也有小團隊的挑戰和成長空間。聯系: qingguang.meiqg at alibaba-inc.com 首先請原諒我的標題...
摘要:調用函數后和普通函數不同的是,該函數并不立即執行,也不返回函數執行結果,而是返回一個指向內部狀態的對象,也可以看作是一個遍歷器對象。第一個只是用來啟動函數內部的遍歷器,傳參也沒有多大意義。 之前斷斷續續接觸到了一些ES6的知識,異步編程方面聽得比較多的就是Promise,直到最近比較系統地學習了ES6的新特性才發現Generator這個神奇的存在,它可以實現一些前所未有的事情,讓我頓時...
閱讀 1433·2021-09-03 10:29
閱讀 3458·2019-08-29 16:24
閱讀 2010·2019-08-29 11:03
閱讀 1410·2019-08-26 13:52
閱讀 2925·2019-08-26 11:36
閱讀 2787·2019-08-23 17:19
閱讀 560·2019-08-23 17:14
閱讀 812·2019-08-23 13:59