av人人干_女狠狠噜天天噜日日噜_国产精品一区二区免费_亚洲国语自产一区第二页_免费av观看_已婚少妇露脸日出白浆_国产精品探花视频_久久国产精品2020免费_国产精品好好热av在线观看_亚洲另类春色校园小说

網站建設知識

我們將想法與焦點與您一起共享

當前位置:深圳網站建設 > 網站建設知識> 深圳網站建設|用Generators解決callback金字塔

深圳網站建設|用Generators解決callback金字塔

2017/6/5 17:39:35 獨占網絡 網站建設知識
what is generator

Generators算得上js的一個新概念函數。它看起來像是一個函數,但是可以暫停執行。從語法上看,有3點關注:

函數名前有一個*
函數內有yield
調用時返回一個對象,對這個對象調用next才會繼續執行
你的node支持generator了嗎?

在node 0.11以上,對node必須加入–harmony 參數,即可支持:

JavaScript

$ node --harmony
    > function *a(){}
    undefined
    >
 
看到undefined就說明支持了。如果不加參數,默認不支持。你會看到

JavaScript

$ node
    > function *a(){}
    ... 

聲明一個generator 是這樣的:

JavaScript

  function* ticketGenerator() {} 
如果想要 generator 提供一個值并暫停,那么需要使用yeild 關鍵字。yield 就像 return 一樣返回一個值。和它不同的是,yield會暫停函數。

JavaScript

function* ticketGenerator() {
      yield 1;
      yield 2;
      yield 3;
    } 
我們做了一個迭代器,叫做 ticketGenerator. 我們可以和它要一個值,然后它返回1,然后暫停。依次返回2,3:

JavaScript

    var takeANumber = ticketGenerator();
    takeANumber.next(); 
    // > { value: 1, done: false }
    takeANumber.next(); 
    // > { value: 2, done: false }
    takeANumber.next(); 
    // > { value: 3, done: false }
    takeANumber.next(); 
    // > { value: undefined, done: true } 
現在我們返回大為3 ,不太有用.我們可以遞增到無窮。無窮數列來了。

JavaScript

function* ticketGenerator() {
  for(var i=0; true; i++) {
    yield i;
  }
}
 
再來一遍:

JavaScript

var takeANumber = ticketGenerator();
console.log(takeANumber.next().value); //0
console.log(takeANumber.next().value); //1
console.log(takeANumber.next().value); //2
console.log(takeANumber.next().value); //3
console.log(takeANumber.next().value); //4 
每次疊加,無窮枚舉。這就有點意思了。

干預yield返回值

除了可以枚舉累加外, next() 還有第二種用法:如果你傳遞一個值給next,它會作為yield 語句的返回值。我們可以利用這個特性,把剛剛的無限數列做一次重置:

JavaScript

function* ticketGenerator() {
  for(var i=0; true; i++) {
    var reset = yield i;
    if(reset) { i = -1; }
  }

這樣當我們調用next(true)的時候,i會等于-1,從而重設了i值到初始值。

無需困惑, yield i 會把i發到generator的調用next處,但是generator內部我們使用next提供的值(如果提供了的話)。

看看效果:

JavaScript

var takeANumber = ticketGenerator();
console.log(takeANumber.next().value); //0
console.log(takeANumber.next().value); //1
console.log(takeANumber.next().value); //2
console.log(takeANumber.next(true).value); //0
console.log(takeANumber.next().value); //1 
這就是generator。古怪,有趣。接下來會繼續分析它的應用,在解決callback hell方面。

問題

拿一個案例開刀吧。我們來看一個delay函數,延遲一些時間,然后打印點文字:

JavaScript

function delay(time, callback) {
  setTimeout(function () {
    callback("Slept for "+time);
  }, time);

調用它也是常見代碼:

JavaScript

delay(1000, function(msg) {
  console.log(msg);
  delay(1200, function (msg) {
      console.log(msg);
    }
})
//...waits 1000ms
// > "Slept for 1000"
//...waits another 1200ms
// > "Slept for 1200" 
為了保證兩次打印的次序,我們的辦法,就是通過callback來完成。

要是延遲多幾次,比如12次,我們需要12次嵌套的callback,代碼不段向右延伸。哇,回調金字塔。

呼叫Generators

異步是node的靈魂。可是異步的麻煩在于callback,因為我餓每年需要等待完成通知,所以需要callback。

有了 generators,我們可以讓代碼等。無需callback。可以用generators 在每個異步調用進行中,在調用next()之前暫停執行。還記得yield/next 嗎?這是generators的絕活。

怎么弄?

我們先得知道,我們要把異步調用暫停需要用到generator ,而不是典型的函數,所以加個星在函數前:

JavaScript

function* myDelayedMessages() {
    /* delay 1000 ms and print the result */
    /* delay 1200 ms and print the result */
}
 
加入delay調用。delay需要callback。這個callback需要調用generator.next(),以便繼續代碼。我們先放一個空的callback:

JavaScript

function* myDelayedMessages() {
    console.log(delay(1000, function(){}));
    console.log(delay(1200, function(){}));
}
 
現在代碼依然是異步的。加入yield:

JavaScript

function* myDelayedMessages() {
    console.log(yield delay(1000, function(){}));
    console.log(yield delay(1200, function(){}));
}
 
又近了一步。但是需要有人告訴generator向前走,走起來。

關鍵概念在這里:當delay完成時,需要在它的callback內執行點東西,這些東西讓generator向前走(調用next)

這個函數,且不管如何實現,我們知道它得叫做resume:

JavaScript

function* myDelayedMessages(resume) {
    console.log(yield delay(1000, resume));
    console.log(yield delay(1200, resume));

我們得把定義好的resume傳遞給 myDelayedMessages

變魔術了…

如何實現resume,它又如何知道我們的generator?

給generator 函數加個外套,外套函數的功能就是啟動generator,傳遞寫好的resume,次撥動generator(調用next),等待resume被調用,在resume內繼續撥動generator。這樣generator就可以滾動起來了:

JavaScript

function run(generatorFunction) {
    var generatorItr = generatorFunction(resume);
    function resume(callbackValue) {
        generatorItr.next(callbackValue);
    }
    generatorItr.next()

有點燒腦。當年寫作名噪一時的“goto statement considered harmful”的作者,看到此代碼非得氣死。這里沒有一行goto,卻跳來跳去的比有goto的還難。

注意哦,我們利用了next的第二個特性。resume 就是傳遞給callback 的函數,它因此接受了delay提供的值,resume傳遞這個值給 next, 故而 yield 語句返回了我們的異步函數的結果。異步函數的結果于是被console打印出來。就像“倒脫靴”。

代碼整合起來:

JavaScript

run(function* myDelayedMessages(resume) {
    console.log(yield delay(1000, resume));
    console.log(yield delay(1200, resume));
})
//...waits 1000ms
// > "Slept for 1000"
//...waits 1200ms
// > "Slept for 1200" 
就是這樣。我們調用兩次delay,按照次序執行,卻沒有callback的嵌套。如果要調用12次,也還是沒有callback嵌套。如果你依然迷惑不解,我們再次分步來一遍》

run 以generator 為參數,并且內部創建了一個resume 函數
run 創建一個generator函數,傳遞resume給它
然后run次調用next,啟動了generator函數到yield
generator 遇到了個yield,并調用yield后的delay,然后暫停。
delay 在1000ms后完成,調用resume
resume 告訴generator 在走一步。并且傳遞delay的結果給run函數,由console 打印
generator 遇到第二個yield, 調用delay ,再次暫停
delay 在1200ms后完成,調用resume
resume 告訴generator 在走一步。并且傳遞delay的結果給run函數,由console 打印
co 更好

上面談到的做法,確實可以把異步改成同步了。可是并不太完美:比如resume顯得比較突兀,在比如只能在callback返回一個值。不夠通用。

這樣的話,可以考慮TJ開發的co。連resume的聲明和引用也省掉了。還是以delay為例:

JavaScript

    var co = require('co');
    function delay(time) {
      return function (callback){
        setTimeout(function () {//
          callback(null,"Slept for "+time);
        }, time);
      }
    }

    co(function *() {
      console.log(yield delay(1000))
      console.log(yield delay(1200))  
    }) 
為了和co適配,delay需要做些修改,去掉callback,返回一個帶callback的函數,把計算結果通過callback傳遞出去。個參數依照node的規矩,留給err。

更絕。怪的不TJ被社區成為大神。

再來一個。readFile(file,callback),作為常見的異步函數如何修改?

JavaScript

    var co = require('co');
    function readFile(file){
      return function (callback ){
        var fs = require("fs")
        fs.readFile(file,callback)
      }
    }

    co(function *() {
      console.log(yield readFile("./app.js"))
    })

    //<Buffer 76 61 72 20 63 ... > 
可是,readFile改造這樣過工作,純粹就是boilerplate !所以,有人做了這樣的工作。安裝co-fs,就可以:

JavaScript

    co(function *() {
      var fs = require("co-fs")
      var js = yield fs.readFile('./app1.js', 'utf8')
      var files = yield fs.readdir('.')
      console.log(js,files)
    })
 
node.js真是玩梯云縱。以為已經很好了,還是有人在加入一把火。

所以,值得去npm看看,查找下co-打頭的庫,有1000+個,要不要獨立出去:):
 
打個總結

成功。我們用generator替換了callback。我們這樣做到的:

創建一個run函數,以 generator 為參數, 并傳遞一個 resume 函數給它
傳遞resume 函數,單步推動generator ,返回任何異步callback獲得的值給run
傳遞resume 作為異步調用callback . 這些異步函數一旦完成,就調用callback,因此就是調用resume。允許resume推動generator

generators替代“callback hell” 是否佳是可爭論的,但是這個練習可以幫助你理解到ES6的generators 和iterators

    深圳網站建設www.ykfic.cn

始終專注高端網站建設服務 網站建設案例服務方案聯系

聯系我們

135-3000-5572
151-1257-9390

地址:深圳市龍崗區橫崗街道力嘉創意文化產業園338

郵箱:chenmh@sz886.com

我們的優勢

12年建站服務經驗自主開發后臺CMS開發項目不外包無隱形收費

服務198家上市企業服務行業龍頭超過70家 營銷型網站建設完備的項目流程管理體系網頁設計與網站開發技術并重

關于獨占網絡

十多年來,憑借對設計的深刻理解,對互聯網營銷趨勢的敏銳洞察,獨占網絡不斷修正服務導向,完善創作品格,始終注重專業探索,為所有合作企業機構全力以赴,確保網站的視覺體驗與營銷轉化能力。

我們是一群對互聯網抱有執著信念的技術控。從2012年到現在,公司從未建過強大的營銷團隊,卻憑著作品與服務不斷保持增長,做到了"桃李不言,下自成蹊。" 我們堅信:每個客戶都是一條渠道,每個案例都是一個廣告,為企業插上翅膀,助力企業轉型升級,我們已做好準備。

專業團隊為您提供深圳網站建設、深圳網站制作、深圳營銷型網站建設、外貿網站建設等服務,深圳建網站就找獨占網絡 | 12年專注網站建設

深圳市獨占網絡科技有限公司 |備案號:粵ICP備15007128| Copyright 2025,ALL Rights Reserved www.ykfic.cn | Copyright 2025版權所有
Hi,Are you ready? 如果您有意向
請于我們取得聯系。

有一個互聯網項目想和我們談談嗎?
您可以填寫右邊的表格,讓我們了解您的項目需求,這是一個良好的開始,我們將會盡快與你取得聯系。當然也歡迎您給我們寫信或是打電話,讓我們聽到你的聲音!

獨占-整合互聯網營銷

地址:深圳市龍崗區橫崗地鐵A出口力嘉創意文化產業園338
大客戶專線:深圳 13530005572
售前QQ:1447567909
E-mail: sales@sz886.cn

合作意向表
您希望我們為您提供什么服務?
主站蜘蛛池模板: 瓦房店市| 米泉市| 明水县| 成都市| 顺义区| 沙洋县| 滁州市| 北川| 永城市| 会宁县| 毕节市| 金平| 内丘县| 分宜县| 孙吴县| 中卫市| 沂源县| 奉新县| 通渭县| 民丰县| 南部县| 眉山市| 乐亭县| 城固县| 怀化市| 清苑县| 当阳市| 海晏县| 阿巴嘎旗| 通河县| 通海县| 贵阳市| 东乌| 四子王旗| 昆山市| 娱乐| 长武县| 广东省| 乌苏市| 辽阳县| 唐河县|