国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

理解thunk函數的作用及co的實現

張巨偉 / 2884人閱讀

摘要:從形式上將函數的執(zhí)行部分和回調部分分開,這樣我們就可以在一個地方執(zhí)行執(zhí)行函數,在另一個地方執(zhí)行回調函數。這樣做的價值就在于,在做異步操作的時候,我們只需要知道回調函數執(zhí)行的順序和嵌套關系,就能按順序取得執(zhí)行函數的結果。

thunk

thunk 從形式上將函數的執(zhí)行部分回調部分分開,這樣我們就可以在一個地方執(zhí)行執(zhí)行函數,在另一個地方執(zhí)行回調函數。這樣做的價值就在于,在做異步操作的時候,我們只需要知道回調函數執(zhí)行的順序和嵌套關系,就能按順序取得執(zhí)行函數的結果。

以下是 thunk 的簡單實現:

function thunkify (fn) {
    return function () {
        var args = Array.prototype.slice(arguments);
        var ctx = this;

        return function (done) {
            var called = false;
            args.push(function() {
                if (called) return;
                called = true;
                done.apply(null, arguments);
            });
            try {
                fn.apply(ctx, args);
            } catch (err) {
                done(err);
            }
        }
    }
}

上面的實現將函數原有的執(zhí)行變?yōu)榘础皥?zhí)行部分”和“回調部分”分別執(zhí)行的方式:

fn(a, callback) => thunkify(fn)(a)(callback)

例如:

var fs = require("fs");
var readFile = thunkify(fs.readFile); // 將readFile函數包進thunkify,變?yōu)閠hunkify函數

//**這是執(zhí)行函數集合**//
var f1 = readFile("./a.js");
var f2 = readFile("./b.js");
var f3 = readFile("./c.js");

//**這是回調函數集合**//
//利用嵌套控制f1 f2執(zhí)行的順序
f1(function(err, data1) {
    // doSomething
    f2(function(err, data2) {
        // doSomething
        f3(function (err, data3) {
            // doSomething
        })
    })
})

而傳統(tǒng)的寫法為:

//傳統(tǒng)寫法
fs.readFile("./a.js", function(err, data1) {
    // doSomething
    fs.readFile("./b.js", function(err, data2) {
        // doSomething
        fs.readFile("./c.js", function(err, data3) {
            // doSomething
        })
    })
})

在執(zhí)行部分和回調部分分開之后,就可以使用generator等異步控制技術方便地進行流程控制,避免回調黑洞。上述的文件讀取流程就可以用generator進行改造:

var fs = require("fs");
var readFile = thunkify(fs.readFile);

//**函數的‘執(zhí)行部分’放在一起執(zhí)行**//
var gen = function* () {
    var data1 = yield readFile("./a.js");
    // 用戶獲取數據后自定義寫在這里
    console.log(data1.toString());
    
    var data2 = yield readFile("./b.js");
    // 用戶獲取數據后自定義寫在這里
    console.log(data2);
    ····
}

// 函數的‘回調部分’在另一個地方執(zhí)行,且調用的形式都一樣
var g = gen();
var d1 = g.next(); // 返回的結果為{value: func, done: boolean}

// 執(zhí)行value,實際為執(zhí)行`d1.value(callback)`
// 也即`thunkify(fs.readFile)("./a.js")(callback)`
d1.value(function(err, data) {
    if (err) throw err;
    // g.next(data) 可以將參數data傳回generator函數體,作為上一個階段異步任務的執(zhí)行結果
    // 例子中,data被傳回了gen函數體,作為data1的值
    var d2 = g.next(data);
    d2.value(function(err, data2) {
        if (err) throw err;
        g.next(data2);
    });
});
co

在上述的改造中發(fā)現,執(zhí)行回調部分的時候,依舊存在回調嵌套:d2.valued1.value的回調中執(zhí)行。觀察后發(fā)現,其實在執(zhí)行回調的時候,也就是g在執(zhí)行next()的時候,執(zhí)行的形式基本相同,都是:

d.value(function(err, data) {
    if (err) throw err;
    g.next(data);
});

這種形式,所以可以通過編寫一個遞歸函數來整理流程。

function run(fn) {
    var g = fn();
    
    // 下一步控制函數,實際就是d.value的回調函數
    function next(err, data) {
        // 把前面一個數據給傳遞到gen()函數里面
        var result = g.next(data);
        // 判斷是否結束
        if (result.done) return;
        // 下一句執(zhí)行回調next的時候 不斷的遞歸
        result.value(next);
    }
    // 執(zhí)行第一步
    next();
}

// 使用
run(gen);

上面代碼中的過程很好理解,就是把gen放到一個遞歸器中去執(zhí)行,在這個遞歸器中有一個核心的函數next,這個函數就是遞歸函數。當函數中的g.next(data)返回的done屬性值為true,就表示當前生成器函數中的yield已經執(zhí)行完畢,退出就OK。當不為true,表示當前生成器函數還有未執(zhí)行的yield,于是繼續(xù)調用next函數繼續(xù)執(zhí)行同樣的流程。

而上述的流程就是異步流控制庫co的簡單實現。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90633.html

相關文章

  • co模塊用法分析

    摘要:模塊可以將異步解放成同步。源碼分析使用的模塊版本號為首先看一些用于判斷對象類型的函數對數組方法的引用這兩個應該就不用說了吧。。。看一下模塊的輸出部分因此以下三種用法等價接著就是重頭戲函數了。 本文只在個人博客和 SegmentFault 社區(qū)個人專欄發(fā)表,轉載請注明出處 個人博客: https://zengxiaotao.github.io SegmentFault 個人專欄: h...

    muzhuyu 評論0 收藏0
  • Node.js 異步異聞錄

    摘要:的異步完成整個異步環(huán)節(jié)的有事件循環(huán)觀察者請求對象以及線程池。執(zhí)行回調組裝好請求對象送入線程池等待執(zhí)行,實際上是完成了異步的第一部分,回調通知是第二部分。異步編程是首個將異步大規(guī)模帶到應用層面的平臺。 showImg(https://segmentfault.com/img/remote/1460000011303472); 本文首發(fā)在個人博客:http://muyunyun.cn/po...

    zzbo 評論0 收藏0
  • JavaScript 異步隊列Co實現

    摘要:在中,又由于單線程的原因,異步編程又是非常重要的。方法有很多,,,觀察者,,,這些中處理異步編程的,都可以做到這種串行的需求。 引入 隊列對于任何語言來說都是重要的,io 的串行,請求的并行等等。在 JavaScript 中,又由于單線程的原因,異步編程又是非常重要的。昨天由一道面試題的啟發(fā),我去實現 JS 中的異步隊列的時候,借鑒了 express 中間件思想,并發(fā)散到 co 實現 ...

    LdhAndroid 評論0 收藏0
  • co-parallel & co-gather源碼解析

    摘要:昨天也是好好的看了一下的源碼,今天打算自己來做一下解析。源碼如下這段代碼真的是很短,但是方法真的很巧妙。因為兩個方法用到了,這里把的源碼也貼出來源碼的描述就是為了執(zhí)行而創(chuàng)建的。最后再次感謝提供的思路。 原文鏈接,轉載請注明出處 最近看了Ma63d關于爬蟲的這篇文章,正好自己也在做爬蟲,看到他在文中提到了co-parallel和co-gather,就打算改一下自己的代碼(本來代碼就只是為...

    caozhijian 評論0 收藏0
  • 《Node.js設計模式》基于ES2015+回調控制流

    摘要:以下展示它是如何工作的函數使用構造函數創(chuàng)建一個新的對象,并立即將其返回給調用者。在傳遞給構造函數的函數中,我們確保傳遞給,這是一個特殊的回調函數。 本系列文章為《Node.js Design Patterns Second Edition》的原文翻譯和讀書筆記,在GitHub連載更新,同步翻譯版鏈接。 歡迎關注我的專欄,之后的博文將在專欄同步: Encounter的掘金專欄 知乎專欄...

    LiuRhoRamen 評論0 收藏0

發(fā)表評論

0條評論

張巨偉

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<