JS中的洋葱模型

洋葱模型是一种很经典的程序设计思路:

function compose (middleware) {
  // some code
}
复制代码

它能接受一个函数数组,然后返回一个新的函数,达到这样的效果:

let middleware = []
middleware.push((next) => {
	console.log(0)
	next()
	console.log(3)
})
middleware.push((next) => {
	console.log(1)
	next()
	console.log(1.1)
})
middleware.push(() => {
    console.log(2)
})

let fn = compose(middleware)
fn()

/*
0
1
2
1.1
3
*/
复制代码

当我们尝试执行fn的时候,它会按照顺序调用之前函数数组中的函数,并且给每一个小函数传递一个参数: next函数。

如果在小函数中执行next,就会调用这个函数的下一个函数,如果没有执行next,程序就不会往下走。所以你可以看到上面的打印顺序。

但是问题来了,我们怎么写这个compose函数?

首先, 这个compose函数肯定会返回一个大的函数嘛,所以:

function compose (middleware) {
  return function () {
  }
}
复制代码

然后返回的函数是fn,如果我们尝试执行fn, fn将会尝试执行middleware[0],同时就想我们之前说的,它会给这个小函数传入一个next函数

function compose (middleware) {
  return function () {
    let f1 = middleware[0]
    f1(function next(){
    })
  }
}
复制代码

然后这个next函数有开关的功能,如果我们执行next函数,next函数就会调用数组中下一个函数,所以

function compose (middleware) {
  return function () {
    let f1 = middleware[0]
    f1(function next(){
      let f2 = middleware[1]
      f2(function next(){
        ...
      })
    })
  }
}
复制代码

然后。。。这是递归!为了让上面的更优雅,我们可以这样写

function compose (middleware) {
   return function () {
      dispatch(0)
      function dispatch (i) {
         const fn = middleware[i]
         if (!fn) return null
         fn(function next () {
            dispatch(i + 1)
         })
      }
   }
}
复制代码

通过一个dispatch来优雅的实现递增。

然后我们还希望这个函数支持异步函数:

function compose (middleware) {
   return async function () {
      await dispatch(0)
      function async dispatch (i) {
         const fn = middleware[i]
         if (!fn) return null
         await fn(function next () {
            dispatch(i + 1)
         })
      }
   }
}
复制代码

最后一步,允许用户传递参数

function compose (middleware) {
   return async function () {
      let args = arguments
      await dispatch(0)
      function async dispatch (i) {
         const fn = middleware[i]
         if (!fn) return null
         await fn(function next () {
            dispatch(i + 1)
         }, ...args)
      }
   }
}
复制代码

参考: koa-compose

源代码: github

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值