koa的中介軟體執行的流程控制,**的是非常精妙的。由下面的一張洋蔥模型的圖來形容,記住這張圖。
為什麼是這樣子的圖,下面我們有乙個例子來描述一下
const koa = require('koa')
// fn1
console.log('fn1-1')
next()
console.log('fn1-2')
})// fn2
console.log('fn2-1')
next()
console.log('fn2-2')
})// fn3
console.log('fn3-1')
next()
console.log('fn3-2')
})// fn1-1、fn2-1、fn3-1、fn3-2、fn2-2、fn1-2
上面的這個例子,順序列印出來的是fn1-1、fn2-1、fn3-1、fn3-2、fn2-2、fn1-2
,現在只知道,呼叫next()
函式就會把控制流程就跳到下乙個中介軟體,知道執行所有完之後然後再逐步向上執行前乙個next
後面的**。這根跟洋蔥有很大的相像似性(如果你願意一層一層一層的剝開我的心~~~)。
但是其中的原理是什麼呢??下面我們一步步去探索。
constructor()
use(fn)
就是把所有函式push
到乙個middleware
的陣列之中,這個use
就是專門幹這中勾當的。
好了知道use
的作用了,執行了use
之後 我們的middleware
中就有很多中介軟體函式了,下面我們繼續看下去。
listen(...args)
我們看到裡麼有個this.callback()
執行函式,然後我們跳到這個函式裡面。
callback() ;
return handlerequest;
}
這個callback
函式裡面,執行了compose
函式,並且把middleware
陣列作為引數傳遞進去。
執行到了compose
函式,下面我們就看看compose
裡面有什麼。
compose
函式就是一開始引用了koa-compose
模組,簡化之後發現裡面的**如下,簡化後就簡簡單單的20幾行**,後面會詳細解釋下面的**。
function compose (middleware) ))
} catch (err) }}}
執行這個compose
返回乙個函式,這也是最核心的乙個函式。注意這是上面的callback
呼叫的。得到乙個fn
函式
看上面的callback
呼叫的
然後執行到this.handlerequest(ctx, fn);
這個函式吧ctx
和fn
(這個就是上面compose返回的函式)作為引數,傳入到this.handlerequest中。 **如下。
handlerequest(ctx, fnmiddleware)
到這裡才真正的執行了compose
返回的函式,把ctx
傳進去。然後我們繼續看這個函式fnmiddleware(ctx)
,其實就是下面這樣子的。
function (context, next) ))
} catch (err)
}}
上面的**是這個部分的精華。這裡詳細的說一下,首先定義了乙個index
和dispatch
函式, 然後一開始呼叫dispatch(0)
函式,裡面把0賦值給了index
,然後從middleware
的陣列(例子中我們有三個中介軟體函式)中拿到第0
個中介軟體函式,賦值給fn
,經過兩個if
都不符合條件,然後執行
return promise.resolve(fn(context, function next () ))
這裡的執行fn
中介軟體函式,並且把ctx
和function next () )
作為引數傳遞進去。這個時候**如下一幕了然
console.log('fn1-1')
next() // 執行傳入的next
console.log('fn1-2')})
執行這個函式 就會列印出fn1-1
然後就會執行next()
函式,看上上一塊**
,執行next()
函式裡面會呼叫dispatch(i + 1)
也就是呼叫第fn = middleware[1]
正是第二個中介軟體。
看到這裡大家就大概明白了。然後進入第二個中介軟體執行fn
,列印出fn2-1
,繼續執行next()
函式,next函式裡面繼續呼叫dispatch(i + 1)
,
也就是fn = middleware[2]
第三中介軟體函式,列印出fn3-1
,繼續執行next()
函式裡面會呼叫dispatch(i + 1)
,也就是fn = middleware[3]
,
這裡注意了,if (i === middleware.length) fn = next
到這裡會符合這個條件,然後把next
賦值給fn
這裡的next
就是這個fnmiddleware(ctx).then(handleresponse).catch(onerror);
呼叫時候傳入的,然而這裡並沒有傳入,所以這時候fn
就是undefined
,然後繼續執行到if (!fn) return promise.resolve()
返回乙個空的值,這就是第三個中介軟體的next
執行結果,
然後繼續執行下一行就列印出了fn3-2
,最後向上執行到fn2-2
,然後到fn1-2
, 整個中介軟體的執行過程。很像洋蔥模型,一層層進入,然後一層層出來。
好了整個中介軟體執行過程就是醬紫啦~~~
最後安利一波部落格:
一步步去閱讀koa原始碼,中介軟體執行原理
koa的中介軟體執行的流程控制,的是非常精妙的。由下面的一張洋蔥模型的圖來形容,記住這張圖。為什麼是這樣子的圖,下面我們有乙個例子來描述一下 const koa require koa fn1 console.log fn1 1 next console.log fn1 2 fn2 console....
一步步學ROS
最近因為看svo的 裡面用到catkin決定要好好看ros,年前學會基本操作。啟動節點 rosrun package name executable name 檢視節點 rosnode list 注 rosout 節點是乙個特殊的節點,通過 roscore 自動啟動 檢視特定節點的資訊 rosnod...
windows Thrift c 一步步搭建
1.thrift 原始碼路徑 2.libevent原始碼路徑 3.boost路徑 安裝 conan install boost 1.68.0 conan stable 4.openssl路徑 安裝 conan install openssl 1.1.1a conan stable conan安裝bo...