koa洋葱圈
koa的中间件刚开始看感觉好神奇
serve.use(async (ctx, next) => {
console.log('1 start')
next()
console.log('1 end')
})
serve.use(async (ctx, next) => {
console.log('2 start')
next()
console.log('2 end')
})
serve.use(async (ctx, next) => {
console.log('3 start')
})
// 请求进来后会打印 '1 start' '2 start' '3 start' '2 end' '1 end'
koa做了什么事情呢?自己先分析了一下,大概是将事件存成队列,按顺序执行,将next后的代码缓存执行。
怎么缓存next后的代码???
函数组合
若干个函数组成一个新的函数,同时完成数据的传递
// 简单实现
let add = (a, b) => a + b;
let square = a => a * a;
// 我们将其组合使用
let compose = (fn1, fn2) => (...args) => fn2(fn1(...args))
compose(add, square)(1,2) // 9
// 升级
let compose = (...fns) => {
let n = 0
let res;
return function (...args) {
return dispatch(0)
function dispatch(n) {
let fn = fns[n]
if (!fn) return res
if(n === 0) {
res = fn(...args)
} else {
res = fn(res) // 闭包传递了参数
}
return dispatch(n + 1)
}
}
}
next
当我们不需要传递数值,需要传递回调时
server.use(callback)会将回调函数push到一个队列中
// koa中的use接收一个callback 其中参数ctx next,我们先不管ctx先来看next的功能
// 执行next之前的代码顺序执行,next后的代码从后向前执行
// 我们可以将next中执行队列中下一个函数
let compose = (...fns) => {
let n = 0
return function () {
return dispatch(0)
function dispatch(n) {
let fn = fns[n]
if (!fn) return
fn(function next() {
dispatch(n+1)
})
}
}
}
// 这样我们简单的实现了next功能
需要将其改为Promise
let compose = (middleWares) => {
return function (ctx) {
dispatch(0)
async function dispatch(n) {
let fn = middleWares[n]
if(!fn) return Promise.resolve()
return Promise.resolve(fn(function next() {
return dispatch(n+1)
}))
}
}
}
这个真就是洋葱的感觉 从外到内,从内至外
.....
(未完待续)