Koa compose源碼解析

compose是koa的核心組件,負(fù)責(zé)中間件注冊后的調(diào)用筷转,可以實現(xiàn)多函數(shù)的可控鏈?zhǔn)秸{(diào)用。compose的使用如下:

function A(context, next) {
  console.log('A');
  next();
}

function B(context, next) {
  console.log('B');
}

function C(context, next) {
  console.log('C');
  next();
}

const handler = compose([A, B, C]);
handler(null);
console:
  A
  B

上述示例中C不會觸發(fā)因為函數(shù)B中未調(diào)用next()凭戴。

看了以上的代碼箕速,很多人使用koa框架時酪碘,對中間件函數(shù)通過next()觸發(fā)下一個中間件的原理不甚了解。接下來會逐步還原compose的實現(xiàn)盐茎,同時對源碼實現(xiàn)進(jìn)行解讀兴垦。

function compose(funcs) {
    return function(context) {
        return dispatch(0);
        function dispatch(i) {
            return funcs[i](context, dispatch.bind(null, i+1))
        }
    }
}

以上簡單實現(xiàn)了compose函數(shù)字柠,當(dāng)然compose函數(shù)官方實現(xiàn)比這個復(fù)雜探越,但這段代碼可以看出compose函數(shù)的核心原理,compose函數(shù)的核心是建立dispatch函數(shù)和funcs函數(shù)數(shù)組的聯(lián)系募谎。

dispatch調(diào)用流程

compose函數(shù)運行流程如以上所示扶关,我們可以發(fā)現(xiàn)執(zhí)行compose(funcs)(ctx)等價于執(zhí)行disptch(0),執(zhí)行dispatch(i)等價于執(zhí)行funcs[i](ctx, dispatch(null, i+1))数冬。 意不意外节槐,傳給中間件函數(shù)的next參數(shù)就是dispatch.bind(null, i+1),執(zhí)行這個next函數(shù)就會觸發(fā)下一個中間件函數(shù)拐纱。

現(xiàn)在考慮compose函數(shù)的邊際條件铜异,來完成官方實現(xiàn)。

  1. 首先校驗compose函數(shù)的輸入秸架,其輸入必須是一個函數(shù)列表揍庄;
  2. 限制每個中間件函數(shù)中next()的調(diào)用次數(shù),最多只能調(diào)用一次东抹;
  3. 對dispatch的參數(shù)進(jìn)行校驗蚂子,i不能大于函數(shù)列表的長度,即i < funcs.length缭黔;
    接下來實現(xiàn)上述邊際條件:
function compose(funcs) {
    if (!Array.isArray(funcs)) {
      throw new Error('param funcs must be an array');
    }
    for (let i = 0; i < funcs.length; i++) {
      if (typeof funcs[i] !== 'function') {
        throw new Error('param funcs must be an array of functions')
      }
    }
    return function(context) {
        let index = -1;
        if (index === i) {
           throw new Error('next function triggered more than once');
        }
        return dispatch(0);
        function dispatch(i) {
            index++;
            return i < funcs.length ? funcs[i](context, dispatch.bind(null, i+1)) : null;
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末食茎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子馏谨,更是在濱河造成了極大的恐慌别渔,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惧互,死亡現(xiàn)場離奇詭異哎媚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)喊儡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門拨与,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人艾猜,你說我怎么就攤上這事截珍∨噬酰” “怎么了?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵岗喉,是天一觀的道長。 經(jīng)常有香客問我炸庞,道長钱床,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任埠居,我火速辦了婚禮查牌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘滥壕。我一直安慰自己纸颜,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布绎橘。 她就那樣靜靜地躺著胁孙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪称鳞。 梳的紋絲不亂的頭發(fā)上涮较,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天,我揣著相機(jī)與錄音冈止,去河邊找鬼狂票。 笑死,一個胖子當(dāng)著我的面吹牛熙暴,可吹牛的內(nèi)容都是我干的闺属。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼周霉,長吁一口氣:“原來是場噩夢啊……” “哼掂器!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起诗眨,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤唉匾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后匠楚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巍膘,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年芋簿,在試婚紗的時候發(fā)現(xiàn)自己被綠了峡懈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡与斤,死狀恐怖肪康,靈堂內(nèi)的尸體忽然破棺而出荚恶,到底是詐尸還是另有隱情,我是刑警寧澤磷支,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布谒撼,位于F島的核電站,受9級特大地震影響雾狈,放射性物質(zhì)發(fā)生泄漏廓潜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一善榛、第九天 我趴在偏房一處隱蔽的房頂上張望辩蛋。 院中可真熱鬧,春花似錦移盆、人聲如沸悼院。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽据途。三九已至,卻和暖如春剑鞍,著一層夾襖步出監(jiān)牢的瞬間昨凡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工蚁署, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留便脊,地道東北人。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓光戈,卻偏偏與公主長得像哪痰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子久妆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,870評論 2 361

推薦閱讀更多精彩內(nèi)容