欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

異步編程之Generator(2)——剖析特性

系統(tǒng) 2202 0

異步編程系列教程:

  1. (翻譯)異步編程之Promise(1)——初見魅力
  2. 異步編程之Promise(2):探究原理
  3. 異步編程之Promise(3):拓展進(jìn)階
  4. 異步編程之Generator(1)——領(lǐng)略魅力
  5. 異步編程之Generator(2)——剖析特性
  6. 異步編程之co——源碼分析

Generator基礎(chǔ)


繼上一篇見識(shí)過其配合promise帶來的超爽的異步編程體驗(yàn),我想應(yīng)該大部分同學(xué)都會(huì)想好好看一下,到底這個(gè)Generator是什么?接下來我們會(huì)對(duì)Generator的特性進(jìn)行剖析,讓我們對(duì)接下來學(xué)習(xí) co 源碼打個(gè)扎實(shí)的基礎(chǔ)。

起源

我們首先得知道,Generator一開始并不是用來做異步編程的,是后來的大牛們挖掘了它的特性,讓它在異步編程里大放異彩。其實(shí)Generator是生成遍歷器的構(gòu)造器,ES6定義了一個(gè)遍歷器的接口Iterator。任何數(shù)據(jù)結(jié)構(gòu)滿足Iterator接口,都可以統(tǒng)一實(shí)現(xiàn)遍歷操作。一步一步的調(diào)用 next() 或者 for..of 循環(huán)都可以遍歷實(shí)現(xiàn)Iterator接口的數(shù)據(jù)結(jié)構(gòu)。

我們簡單說一下遍歷對(duì)象的 next() 是怎樣的:

  1. 第一次調(diào)用 next() 會(huì)直接指向第一個(gè)數(shù)據(jù)的位置,然后返回?cái)?shù)據(jù)的信息。結(jié)構(gòu)是這樣的: {value: AnyType, done: Boolean} value 屬性是指該數(shù)據(jù)的值, done 則是標(biāo)志是否已經(jīng)true,結(jié)束了。
  2. 再一次調(diào)用 next() 則指向下一個(gè)數(shù)據(jù),返回相應(yīng)的數(shù)據(jù)信息。
  3. 重復(fù)第二步,一直到數(shù)據(jù)結(jié)束,返回 {value: undefined, done: true} 。則表示遍歷已經(jīng)全部完成。

這就是Iterator最基本的實(shí)現(xiàn),當(dāng)然這里是很片面的,若要展開說,基本又是一大篇文章可以寫。這里就直接給出阮一峰老師關(guān)于Iterator的文章: 10. Iterator和for...of循環(huán)

定義

在我們知道了Generator生成的遍歷對(duì)象是什么之后,我們看一下如何定義這樣的Generator函數(shù)。對(duì)上一篇有印象的同學(xué),應(yīng)該記得函數(shù)標(biāo)識(shí)符后面有一個(gè)詭異的星號(hào) function* () 。其實(shí)這個(gè)星號(hào)在括號(hào)前也是沒關(guān)系的,這里我是參考了 co 源碼的。我們一旦定義了一個(gè)帶星號(hào)的函數(shù)之后,用這個(gè)構(gòu)造器生成的對(duì)象在harmony模式里就成了Generator對(duì)象(下面我會(huì)稱其為遍歷器)。我們可以測試一下一段代碼。

    
      var toString = Object.prototype.toString;

var Generator = function* (){
    yield "hello";
    yield "world";
};

var gen = Generator(); // 可以省去new來創(chuàng)建對(duì)象

console.log(toString.call(Generator)); // [object Function]
console.log(toString.call(gen));       // [object Generator]
    
  

這樣我們通過調(diào)用特殊定義的Generator構(gòu)造器,生成一個(gè)遍歷器([object Generator])。那我們要遍歷的話必須得知道遍歷的每個(gè)成員, yield 就是用來定義遍歷成員的。也就是說,遍歷器進(jìn)行遍歷的時(shí)候會(huì)以 yield 為間隔,一個(gè) yield 一個(gè)成員,不斷往下走直到不存在下一個(gè) yield

在上面的例子中,就是第一次遍歷到 yield 得到"hello",第二次繼續(xù)執(zhí)行遍歷操作到 yield 得到"world",最后再執(zhí)行就發(fā)現(xiàn)沒有了,也就是 done: true 結(jié)束遍歷。

接下來我們會(huì)詳細(xì)說一下,遍歷器是遍歷的各種特性。

Generator特性


遍歷

我們需要執(zhí)行遍歷,首先就是要得到遍歷器。前面也說過了,就是調(diào)用Generator構(gòu)造器生成的。然后該遍歷器會(huì)有一個(gè)方法 next() 用來進(jìn)行遍歷操作,并且每一次的操作都會(huì)在 yield 處停止,并等待下一次的 next() 指令。我們看一看剛才的代碼:

    
      var Generator = function* (){
    yield "hello";
    yield "world";
};

var gen = new Generator();

console.log(gen.next()); // { value: 'hello', done: false }
console.log(gen.next()); // { value: 'world', done: false }
console.log(gen.next()); // { value: undefined, done: true }
    
  

我們可以看到最后當(dāng) done: true 時(shí), value 是undefined。其實(shí)我們r(jià)eturn出去一個(gè)值,就會(huì)成為該 value 的值。其實(shí)換一個(gè)角度更加有意思,就是當(dāng)你return出一個(gè)值,這個(gè)值必定是 done: true 。我們可以改一下上面的例子:

    
      var Generator = function* (){
    yield "hello";
    return "world";
    yield "!";
};

var gen = new Generator();

console.log(gen.next()); // { value: 'hello', done: false }
console.log(gen.next()); // { value: 'world', done: true }
console.log(gen.next()); // { value: undefined, done: true }
    
  

我們可以看到,如果遍歷器去找感嘆號(hào)的 yield 話,應(yīng)該是 value: '!' 。但是因?yàn)樘崆皉eturn結(jié)束了遍歷器,所以最后得到了 { value: 'world', done: true }

yield傳值

我們知道了每一次遍歷器執(zhí)行到 yield 處后,會(huì)把值放在一個(gè)對(duì)象中的屬性中返回出去。但是我們在Generator構(gòu)造器里怎么利用這個(gè)值呢?其實(shí)我們可以為遍歷器的 next(res) 傳入一個(gè)參數(shù),這個(gè)參數(shù)將會(huì)成為這一次 yield 的值。乍一看,好像不大清楚,看看代碼就懂了。

    
      var Generator = function* (){
    var hello = yield "hello";
    console.log(hello);           // hi
    var world = yield "world";
    console.log(world);           // undefined
};

var gen = new Generator();

var first = gen.next("nothing");
var second = gen.next("hi");
var third = gen.next();
    
  

我們第一次 next() 相當(dāng)于啟動(dòng)器,這個(gè)時(shí)候傳入任何參數(shù)都是被忽略的,因?yàn)檫@個(gè)參數(shù)無法作為上一個(gè) yield 的值(沒有上一個(gè))。到我們第二次的 next("hi") ,傳入了一個(gè)"hi"字符串,這個(gè)參數(shù)就成為了 yield 的值,直接賦值給hello變量并打印出來。我們最后一個(gè)world變量是undefined,是因?yàn)? next() 并沒有傳入任何參數(shù)。可以這么說,每一次遍歷器遍歷得到的成員的值,和 yield 的值是沒有必然聯(lián)系的。

所以我們看代碼的執(zhí)行順序也是很有趣的一件事,遍歷器會(huì)執(zhí)行到語句 yield 右側(cè)即停止。等到下一次 next() 啟動(dòng),然后才會(huì)根據(jù) yield 得到的值,對(duì)語句左側(cè)變量進(jìn)行賦值。這樣想的話,如果我們下一次 yield 語句,依賴第一次的值,我們就需要在 next() 里傳入上一次的 value 。我們對(duì)上一次的代碼做個(gè)小小的添加。

    
      var first = gen.next("nothing");
var second = gen.next("hi");
var third = gen.next(second.value); //構(gòu)造函數(shù)的world變量值也會(huì)是"hi"。
    
  

這個(gè)是Generator非常重要的特性,下去要好好實(shí)踐一番,加深印象。接下來 co 源碼分析,這個(gè)特性配合promise可以放華麗的大招。

遍歷遍歷器里的遍歷器

我起這個(gè)標(biāo)題挺有意思的,哈哈哈。其實(shí)就和遞歸棧差不多,也就是說,當(dāng) yield 的是另一個(gè)遍歷器,那么代碼會(huì)進(jìn)入到另一個(gè)遍歷器里,直到結(jié)束后,才交回代碼控制權(quán)。看一看咯:

    
      var Generator = function* (){
    yield  "hello";
    yield *anotherGen;
    yield "world";
    return "hello world";
};

var AnotherGenerator = function* (){
    yield "強(qiáng)勢插入!";
    yield "不給hello world!";
}

var gen = new Generator();
var anotherGen = new AnotherGenerator();

console.log(gen.next()); // { value: 'hello', done: false }
console.log(gen.next()); // { value: '強(qiáng)勢插入!', done: false }
console.log(gen.next()); // { value: '不給hello world!', done: false }
console.log(gen.next()); // { value: 'world', done: false }
console.log(gen.next()); // { value: 'hello world', done: true }
    
  

當(dāng)我們需要遍歷一個(gè)遍歷器,那么 * 也是需要的,可以參考一下上面。

總結(jié)


我們知道了遍歷對(duì)象遍歷時(shí)得到的什么,還有 next(res) 傳入?yún)?shù)有什么用,這對(duì)接下來的分析有著至關(guān)重要的作用。到這里,對(duì)Generator分析已經(jīng)是差不多了。如果想要更深入了解的,可以去阮老師的博客看一看: 11. Generator函數(shù)

接下來一篇文章就是對(duì) co 源碼的分析,先預(yù)習(xí)和復(fù)習(xí)一些東西吧。我們回顧一下promise,我們在將一個(gè)異步操作promise化后,當(dāng)我們調(diào)用這個(gè)異步操作,我們會(huì)得到一個(gè)promise對(duì)象。所以我們可以想象一下:

  1. 我們調(diào)用遍歷器的 next() 得到該異步的promise對(duì)象
  2. 在promise對(duì)象的 then() 中的 resolve 對(duì)數(shù)據(jù)進(jìn)行處理
  3. 把數(shù)據(jù)作為參數(shù)傳入 next(res) ,進(jìn)行下一次異步操作
  4. 直到迭代器的 done: true ,結(jié)束遍歷。

這樣我們就可以一環(huán)扣一環(huán)的將Generator函數(shù)里的異步操作進(jìn)行迭代,形成一種異步編程同步寫法的優(yōu)良體驗(yàn)。當(dāng)然我們這里不會(huì)詳細(xì)說,如何去實(shí)現(xiàn),因?yàn)槲視?huì)在下一篇好好講講。

異步編程之Generator(2)——剖析特性


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 免费99热在线观看 | 色.com| 国产在线观看一区二区三区 | 天天天天做夜夜夜夜 | 国产精品国产午夜免费福利看 | 免费又色又爽1000禁片 | 秋霞影院精品久久久久 | 国产视频久久久 | 日韩一级大毛片欧美一级 | 亚洲无线视频 | 精品欧美一区二区精品久久久 | 99福利| 国产精品毛片一区二区在线看 | 黄网免费看 | 毛片在线不卡 | 色吟av| 国产 欧美 日韩 一区 | 黄色羞羞视频在线观看 | 9久9久女女免费精品视频在线观看 | 天天精品视频免费观看 | 欧美国产另类 | 国产精品午夜电影 | 精品久久久久久久久久久久 | 国内精品免费一区二区观看 | 激情综合五月 | 浮力影院最新地址 | 艹逼视频免费 | 亚洲成人另类 | 总攻调教各种受肉 | 欧美特黄aaaaaaaa大片 | 欧美一区二区在线观看 | 免费观看一级欧美在线视频 | 日本高清中文字幕一区二区三区 | 久久亚洲国产成人影院 | 欧美性一区 | 91视频精选| 午夜视频日本 | 亚洲国产第一区 | 成人国产精品免费视频不卡 | a久久久久一级毛片护士免费 | 国产成人黄网址在线视频 |