责任链模式
-
模式定义
责任链模式 又被叫作 职责链模式 是一种行为设计模式,允许你将请求沿着处理者链进行发送
收到请求后, 每个处理者均可对请求进行处理,或将其传递给链上的下个处理者
-
模式作用
既可以
控制请求处理的顺序,又可以在不更改现有代码的情况下在程序中新增处理者最重要的是
处理者可以决定不再沿着链传递请求,这可高效地取消所有后续处理步骤 -
生活示例(公司采购审批流程)
金额 5 万元以内,主任一人审批即可;
金额大于等于 5 万元小于 10 万元,需要主任和副董事长审批;
金额大于等于 10 万元小于 50 万元,需要主任、副董事长和董事长审批;
金额大于等于 50 万元,需要主任、副董事长、董事长和董事会审批
设计通用轮子
-
基础设计
class Chain { constructor() { this.middleware = [] } // 添加执行节点,也就是中间件 use(fn) { if (typeof fn !== 'function') { throw new TypeError('Middleware must be composed of functions!') } this.middleware.push(fn) // 返回 this 让其可以链式调用 return this } // 接收上下文,并触发责任链执行 transmit(ctx) { this.compose(this.middleware)(ctx) } } -
核心方法
function compose(middleware = []) { if (!Array.isArray(middleware)) { throw new TypeError('Middleware stack must be an array!') } return (context, next) => { let index = -1 const dispatch = i => { // 通过索引来限制 next() 只能被调用一次;如果 next() 被多次调用,则抛出错误 if (i <= index) return Promise.reject(new Error('next() called multiple times')) index = i // 陆续取出 middleware 中的每个函数并开始执行 let fn = middleware[i] // 直到最后一个时,next 为 undefined,此时的 fn 不是函数,直接返回 resolve if (i === middleware.length) fn = next if (!fn) return Promise.resolve() // 如果不是最后一个,则也会返回一个 resolve,但 resolve 的内容是取到下一个 middleware 中的函数 try { // 当执行到 next() 函数时,会调用下一个中间件,会重新 return 进入 dispatch 函数内部,继续执行下一个函数 return Promise.resolve(fn(context, dispatch.bind(null, i + 1))) } catch(err) { return Promise.reject(err) } } return dispatch(0) } }借鉴 koa-compose 的优秀源码,详情可参阅 第35期 - 优秀源码之中间件设计思想 一文
-
使用轮子
const chain = new Chain() chain .use(async (ctx, next) => { console.log('1') await next() console.log('1') }) .use(async (ctx, next) => { console.log('2') await next() console.log('2') }) .use(async (ctx, next) => { console.log('3') }) chain.transmit({ name: '传入执行链中的上下文' }) -
应用场景
一起学习,加群交流看 沸点