在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/HTML/ 使用reduce組合無限的函數(shù)調(diào)用鏈

使用reduce組合無限的函數(shù)調(diào)用鏈

一個對象, 對象中有before與enter方法, 其中 before 可以執(zhí)行異步任務(wù), 完成后執(zhí)行回調(diào)再進(jìn)入enter.
現(xiàn)在可能有若干個這樣的對象,要求按順序依次執(zhí)行下來. 示例如下:

var a = {
    before: function(obj, next) {
        console.log("a before!");
        setTimeout(function() {
            next(obj);
        }, 1000);
        return false;
    },
    enter: function(obj) {
        console.log("a entered!");
    }
};
var b = {
    parent: a,
    before: function(obj, next) {
        console.log("b before!");
        setTimeout(function() {
            next(obj);
        }, 1000);
        return false;
    },
    enter: function(obj) {
        console.log("b entered!");
    }
};
var c = {
    parent: b,
    before: function(obj, next) {
        console.log("c before!");
        setTimeout(function() {
            next(obj);
        }, 1000);
        return false;
    },
    enter: function(obj) {
        console.log(" c entered!", obj);
    }
};

// 組裝后的函數(shù)
var fnChain = function(obj) {
    a.before(obj, function(obj) {
        a.enter(obj);
        b.before(obj, function(obj) {
            b.enter(obj);
            c.before(obj, function(obj) {
                c.enter(obj);
            });
        });
    });
};

fnChain({ Status: 1, Data: { name: "Anonymous" } });

示例中的 fnChain 是我手寫出來的, 現(xiàn)實(shí)中不能這樣. 我想實(shí)現(xiàn)一個函數(shù), 可以根據(jù)對象隊列, 自動生成這個 fnChain

比如我已經(jīng)有這么一個隊列, 然后傳給那個函數(shù):

var arr = [d, c, b, a];
getFnChain(arr); // 得到一個 fnChain

怎么實(shí)現(xiàn)這個 getFnChain 呢? 我有一個初步想法是依靠 reduce, 但不幸的是我試了半天, 頭都暈了, 也沒想出來 ╮(╯Д╰)╭ . 看來對 reduce的理解還差得遠(yuǎn).

希望有大神能幫助我. 可以參照示例代碼中的 fnChain , 這就是我最終想獲得的 函數(shù)

能順帶講一下原理就更好了 (?_?)

回答
編輯回答
尐潴豬

先看輸出:
"a before!"
"a entered!"
"b before!"
"b entered!"
"c before!"
"c entered!"
"d before!"
"d entered!"

function Node(name) {
  this.before = function(obj, next) {
    console.log(name + " before!")
    setTimeout(function() {
      next(obj)
    }, 1000)
    return false
  }
  this.enter = function(obj) {
    console.log(name + " entered!")
  }
}


function chain(curr, cb){
  return function(obj){
    curr.before(obj, function(obj){
      curr.enter()
      cb && cb()
    })
  }
}

let arr = ['a', 'b', 'c', 'd']
arr = arr.map(name => new Node(name))
let fnChain = arr.reduceRight((acc, curr) => chain(curr, acc)
                              , null) // initialValue is null
fnChain({ Status: 1, Data: { name: "Anonymous" } })

解釋下 reduce 的執(zhí)行過程(4次回調(diào))

callback acc curr return value
1 null d fnD = chain(d, null)
2 fnD c fnC = chain(c, fnD)
3 fnC b fnB = chain(b, fnC)
4 fnB a fnA = chain(a, fnB)
2018年8月2日 18:35