摘要:前言終于開始寫了,離這個(gè)系列的終結(jié)又進(jìn)了一步。想要看更深度解析的朋友可以移步漫話與異步第三話化異步為同步這里面談及了的底層實(shí)現(xiàn)及的用法。用法在我的理解中,最大的特點(diǎn)就是可以讓函數(shù)在特定的地方停下,等待被喚醒后在函數(shù)內(nèi)部環(huán)境中繼續(xù)執(zhí)行。
前言
終于開始寫generator了,離這個(gè)系列的終結(jié)又進(jìn)了一步。其實(shí)generator我還處在會(huì)用但是不理解原理的狀態(tài),但是知識(shí)不總結(jié),不記錄的話容易忘記,所以我還是把現(xiàn)在的一點(diǎn)心得記錄下來。等到以后有了更深的理解再回來補(bǔ)充。
想要看更深度解析generator的朋友可以移步漫話JavaScript與異步·第三話——Generator:化異步為同步這里面談及了generator的底層實(shí)現(xiàn)及generator的用法。是我看過的文章中自認(rèn)為解釋的最好的一篇,而且篇幅也不長,建議大家去看一看。
根據(jù)一貫的作風(fēng),我們先嘗試自己實(shí)現(xiàn)generator
嘗試ing............
好了嘗試完了,實(shí)現(xiàn)不了,老老實(shí)實(shí)的學(xué)習(xí)generator的用法吧。
在我的理解中,generator最大的特點(diǎn)就是可以讓函數(shù)在特定的地方停下,等待被喚醒后在函數(shù)內(nèi)部環(huán)境中繼續(xù)執(zhí)行。我們結(jié)合代碼來看一看:
注釋:【1】Iterator Object對(duì)象:參考 Iterator 文章比較長,但是如果只是想要了解什么是Iterator Object的話看完第一小節(jié)就足夠了
//輸出分割線的函數(shù),感興趣的可以自行百度如何設(shè)置console.log的樣式 function cut_off(color) { console.log("%c------------------------------------------","color:"+color+";font-size:20px"); } //* 為generator函數(shù)的標(biāo)識(shí),如果我們想要?jiǎng)?chuàng)建一個(gè)generator函數(shù)就必須在function后面加上* function* generator() { let num1, num2; num1 = 123; console.log("num1", num1, "num2", num2); //yield就是該函數(shù)內(nèi)部暫停的地方,暫停的同時(shí)會(huì)把yield后面的值返回出去 yield num1; num2 = 456; console.log("num1", num1, "num2", num2); yield num2; console.log("num1", num1, "num2", num2); return "end" } console.log("generator defined"); //函數(shù)返回一個(gè)Iterator Object對(duì)象; // 但是與普通函數(shù)不同的是,這個(gè)時(shí)候函數(shù)并不執(zhí)行函數(shù)內(nèi)部的代碼 let g = generator(); console.log("g defined"); cut_off("red"); console.log("g.next() run 1"); //開始執(zhí)行函數(shù)內(nèi)部的代碼,并且遇在到y(tǒng)ield的時(shí)候返回 yield后面的值 console.log(g.next()); cut_off("red"); console.log("g.next() run 2"); //從上次執(zhí)行完的地方執(zhí)行,并且遇在到y(tǒng)ield的時(shí)候返回 yield后面的值 console.log(g.next()); cut_off("red"); console.log("g.next() run 3"); //從上次執(zhí)行完的地方執(zhí)行,這次是最后一次有值的返回,done的狀態(tài)會(huì)變?yōu)閠rue console.log(g.next()); cut_off("red"); console.log("g.next() run 4"); //已經(jīng)執(zhí)行完成之后再次被調(diào)用,永遠(yuǎn)返回{value:undefined, done: true} console.log(g.next()); cut_off("red"); console.log("g.next() run 5"); //已經(jīng)執(zhí)行完成之后再次被調(diào)用,永遠(yuǎn)返回{value:undefined, done: true} console.log(g.next());
貼上一張代碼和運(yùn)行結(jié)果的對(duì)比圖輔助大家理解
希望大家看到這里已經(jīng)理解了generator的基本用法,但是這個(gè)東西確實(shí)有點(diǎn)難,所以我放出聯(lián)系方式
我有空的時(shí)候可以一起探討一下
接下來我要講generator最重要的第二個(gè)特性,我們可以通過.next(value)為yeild賦值(這是不準(zhǔn)確的說法,但是我們可以這么理解,方便我們使用generator),還是貼代碼:
function* generator() { //第一次調(diào)用.next()是啟動(dòng)了這個(gè)函數(shù)一直運(yùn)行到下一個(gè)yield的位置 let num1, num2; num1 = 123; console.log("num1", num1, "num2", num2); num2 = yield num1;/*1.由于運(yùn)算的順序,js會(huì)先計(jì)算右邊的值,也就是在num2被賦值之前,函數(shù)就停止運(yùn)行了 2.第二次調(diào)用.next(value)的時(shí)候,value被next傳入了yield的位置 3.程序繼續(xù)運(yùn)行,value被賦值給了num2 */ console.log("num1", num1, "num2", num2); return num2 } let g = generator(); console.log("g.next() run 1"); console.log(g.next()); cut_off("red"); console.log("g.next(789) run 2"); //從上次執(zhí)行完的地方執(zhí)行,并且將789傳入函數(shù)內(nèi)部 console.log(g.next(789));
貼出函數(shù)和運(yùn)行結(jié)果的對(duì)比圖,輔助大家理解.next(value)為yeild賦值(該說法并不準(zhǔn)確)
generator的基礎(chǔ)學(xué)習(xí)到這里就能嘗試實(shí)際使用了,接下來我們嘗試讓generator在異步中大展身手吧,話不多說上代碼;
//模擬異步請(qǐng)求 let request = function (sucF, errF) { if ((sucF && typeof sucF !== "function") || (errF && typeof errF !== "function")) { throw new Error("傳入?yún)?shù)必須為函數(shù)") } setTimeout(function () { let data = parseInt(Math.random() * 100); if (data < 90 && sucF) { sucF(data) } else if (errF) { errF("本次異步失敗了") } }, 100) }; function* generator() { let num1, num2; num1 = yield request((data) => { g.next(data) //這個(gè)地方可能有些難以理解,為什么在g被創(chuàng)建之前,就被使用了。 }, err => { //這個(gè)問題可以看注釋【1】來輔助理解 console.error(err); g.return(err) //跳過所有的yield,return直接返回err }); console.log("num1", num1, "num2", num2); num2 = yield request((data) => { g.next(data) }, err => { console.error(err); g.return(err) //跳過所有的yield,return直接返回err }); console.log("num1", num1, "num2", num2); return num2 } let g = generator(); //啟動(dòng) g.next();
注釋【1】:為了解釋g為什么可以在被創(chuàng)建之前就‘被調(diào)用’
//其實(shí)在運(yùn)行g(shù)enerator的時(shí)候generator內(nèi)部的代碼塊并沒有開始運(yùn)行,而是返回了一個(gè)Iterator對(duì)象,所以大家可以這樣簡單理解 //function* generator 相當(dāng)于 function generator(){ let obj = {}; obj.next=function(){ console.log(g); }; return obj } //這樣在調(diào)用generator()的時(shí)候,g不會(huì)被使用 let g = generator(); //這個(gè)時(shí)候g被調(diào)用了,但是在上一行代碼中,g已經(jīng)被定義了,所以沒有問題,不會(huì)報(bào)錯(cuò) g.next()
這篇文章暫時(shí)寫到這里,因?yàn)槲业捻撁骈_始卡了,所以我把generator和promise結(jié)合的用法放到下一篇文章中去;(ps:今天就會(huì)寫出來的)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/103633.html
摘要:你能學(xué)到什么如何使用實(shí)現(xiàn)異步編程異步編程的原理解析前言結(jié)合上一篇文章,我們來聊聊基礎(chǔ)原理說到異步編程,你想到的是和,但那也只是的語法糖而已。表示一個(gè)異步操作的最終狀態(tài)完成或失敗,以及其返回的值。至此實(shí)現(xiàn)異步操作的控制。 你能學(xué)到什么 如何使用 Generator + Promise 實(shí)現(xiàn)異步編程 異步編程的原理解析 前言 結(jié)合 上一篇文章 ,我們來聊聊 Generator 基礎(chǔ)原理...
摘要:對(duì)于而言,異步編程我們可以采用回調(diào)函數(shù),事件監(jiān)聽,發(fā)布訂閱等方案,在之后,又新添了,,的方案??偨Y(jié)本文闡述了從回調(diào)函數(shù)到的演變歷史。參考文檔深入掌握異步編程系列理解的 對(duì)于JS而言,異步編程我們可以采用回調(diào)函數(shù),事件監(jiān)聽,發(fā)布訂閱等方案,在ES6之后,又新添了Promise,Genertor,Async/Await的方案。本文將闡述從回調(diào)函數(shù)到Async/Await的演變歷史,以及它們...
摘要:環(huán)境中產(chǎn)生異步操作的函數(shù)分為兩大類計(jì)時(shí)函數(shù)和函數(shù)。如果要在應(yīng)用中定義復(fù)雜的異步操作,就要使用者兩類異步函數(shù)作為基本的構(gòu)造快。在本例子中同步事件循環(huán)不包含內(nèi)部的外部的異步事件循環(huán)內(nèi)部的。其弊端是操作強(qiáng)耦合維護(hù)代價(jià)高。 JavaScript環(huán)境中產(chǎn)生異步操作的函數(shù)分為兩大類:計(jì)時(shí)函數(shù)和I/O函數(shù)。如果要在應(yīng)用中定義復(fù)雜的異步操作,就要使用者兩類異步函數(shù)作為基本的構(gòu)造快。本文沒有對(duì)某個(gè)知識(shí)點(diǎn)...
摘要:換句話說,當(dāng)一個(gè)異步過程調(diào)用發(fā)出后,調(diào)用者不會(huì)立刻得到結(jié)果。參考文章珠峰架構(gòu)課墻裂推薦細(xì)說異步函數(shù)發(fā)展歷程異步編程謝謝各位小伙伴愿意花費(fèi)寶貴的時(shí)間閱讀本文,如果本文給了您一點(diǎn)幫助或者是啟發(fā),請(qǐng)不要吝嗇你的贊和,您的肯定是我前進(jìn)的最大動(dòng)力。知其然知其所以然,首先了解三個(gè)概念: 1.什么是同步? 所謂同步,就是在發(fā)出一個(gè)調(diào)用時(shí),在沒有得到結(jié)果之前,該調(diào)用就不返回。但是一旦調(diào)用返回,就得到返回值了...
閱讀 1319·2021-11-19 09:40
閱讀 1022·2021-11-12 10:36
閱讀 1335·2021-09-22 16:04
閱讀 3188·2021-09-09 11:39
閱讀 1324·2019-08-30 10:51
閱讀 1946·2019-08-30 10:48
閱讀 1288·2019-08-29 16:30
閱讀 534·2019-08-29 12:37