Skip to content

chain 职责链

概述

该方法的好处是使多个对象都有机会处理请求,从而避免规则与使用之间的耦合,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

通过new Chain(yourRules)传入规则创建节点,使用after通过AOP的方式将不同节点串联chain.after(yourRules2).after(yourRules3)

执行时使用chain.passRequest(yourArgs);,passRequest的参数会统一透传到每个节点规则中

其中rules在不满足当前条件,想要执行下个节点时需要return 'next',或者promise时resolve('next')

示例

假设我们负责一个售卖手机的电商网站,经过分别交纳 500元定金和 200元定金的两轮预定后(订单已在此时生成),现在已经到了正式购买的阶段。 公司针对支付过定金的用户有一定的优惠政策。在正式购买后, 已经支付过 500元定金的用户会收到 100元的商城优惠券, 200元定金的用户可以收到 50元的优惠券, 而之前没有支付定金的用户只能进入普通购买模式,也就是没有优惠券,且在库存有限的情况下不一定保证能买到。

ts
import { Chain } from '@ey-use/utils';
enum EOrderType {
  prepay500,
  prepay200,
  normal,
}
function order500(orderType: EOrderType, pay: boolean, stock: number) {
  if (orderType === EOrderType.prepay500 && pay) {
    console.log('预付500元,得到100优惠');
  } else {
    return 'next';
  }
}

function order200(orderType: EOrderType, pay: boolean, stock: number) {
  if (orderType === EOrderType.prepay200 && pay) {
    console.log('预付200元,得到100优惠');
  } else {
    return 'next';
  }
}

function orderNormal(orderType: EOrderType, pay: boolean, stock: number) {
  if (stock > 0) {
    console.log('普通购买 无优惠券');
  } else {
    console.log('库存不足');
  }
}

const chain = new Chain(order500);
// 将规则串联
chain.after(order200).after(orderNormal);

let stock = 3;
// 使用时直接输入规则,是否付款,库存让链子自己判断
chain.passRequest(EOrderType.prepay200, true, stock--);

由上可看到,若接下来还有不同规则插入或去除时,我们只需修改chain.after即可,各个规则也能独立处理

示例2 异步处理

可采用this.next(需要确保this为Chain的回调所指向的执行环境)或promise.resove来异步运行职责链

ts
const fn1 = new Chain(function(){
    console.log('1')
    setTimeout(()=>{
        this.next()
    },3000)
})
fn1.after(function(){
    return new Promise((resolve)=>{
        console.log('2')
        setTimeout(()=>{
            resolve('next')
        },2000)
    })
}).after(()=>{
    console.log('3')
})
fn1.passRequest()

一个让开发效率增倍的组件库