Koa洋葱圈

285 阅读1分钟

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)
      }))
    }
  }
}

这个真就是洋葱的感觉 从外到内,从内至外

洋葱

.....

(未完待续)