当前位置: 首页 > Web前端 > JavaScript

责任链模型在项目中的应用

时间:2023-03-26 20:32:43 JavaScript

最近在做后台管理系统中的采购订单。一般流程是客户先选择供应商,然后从供应商提供的产品中进行选择。选择后,编辑价格、数量、金额等字段,最终形成一个包含多个产品对象的数组。每个产品对象都有很多与产品相关的属性,如下:constproductList=[{ItemId:2000,//产品IDName:'xxx',//产品名称IsFresh:true,//是否为生鲜商品PurcPrice:20,//文件购买价格Price:21,//价格CostPrice:20,//加权平均价格Qty:30,//数量Amount:630,//小计数量LargeQty:30//箱数//单位,自编码,...}//...]客户编辑后,最后点击保存按钮,调用接口生成采购订单。保存时,需要对客户选择的产品进行一些验证。现在有三种验证规则:商品小计金额(Amount)不能超过99999999,判断是否在购买设置中启用:“当购买价格高于加权平均价格时,提示”,如果启用后,当某商品的进货价格(Price)高于加权平均价格(CostPrice)时,弹框提示未启用进货设置:“生鲜商品的价格允许高于商品文件.price",则当商品为生鲜商品且价格高于文件中的进货价时,弹框提示以上三项勾选相互独立,且有些支票一旦不满足就不能保存(1,3),有些条件不满足,还是可以保存的,让用户选择(2)。为了使这些验证过程相互独立,可以采用责任链模式来管理代码。参考《javascript设计模式与开发实践》中责任链模式的定义:让多个对象有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连接成一条链,并沿着这条链传递请求,直到一个对象处理它。下面是具体的实现方法:/***责任链模式*/exportclassChain{constructor(fn){this.fn=fnthis.successor=null}setNextSuccessor(successor){return(this.successor=successor)}asyncpassRequest(){constres=awaitthis.fn.apply(this,arguments)if(res==='nextSuccessor'&&this.successor){returnawaitthis.successor.passRequest.apply(this.successor,arguments))}returnres}}/***使用责任链模式在保存前进行校验*@param{Object}data需要校验的数据*/asyncfunctionvalidate(data){//校验:最大值小计金额限制functionvalidateAmountMax(){constindex=data.findIndex((item)=>item.Amount>=99999999)if(index>-1){returnnewPromise((resolve)=>{constmodal=Modal.confirm({title:'提示',content:'小计金额不能超过99999999',icon:createVNode(ExclamationCircleOutlined),okText:'OK',cancelText:createVNode(),asynconOk(){nextTick(()=>modal.destroy())resolve(false)}})})}return'nextSuccessor'}//检查:购买价格是否高于加权averagepricefunctionvalidateInPriceHigherThanAutoPrice(){//判断购买设置是否开启:“购买价格高于加权平均价格时提示”,如果开启,//当某商品的购买价格高于加权平均价格时提示均价,弹窗提示if(purchaseSettings.value.InPriceHigherThanAutoPrice=='Y'){constneedTip=data.some((item)=>item.Price>item.CostPrice)if(needTip){returnnewPromise((resolve)=>{constmodal=Modal.confirm({title:'确认',content:'现有商品当前价格高于加权平均价,是否继续保存?',icon:createVNode(ExclamationCircleOutlined),okText:'OK',cancelText:'Cancel',asynconOk(){nextTick(()=>modal.destroy())resolve('nextSuccessor')},异步onCancel(){nextTick(()=>modal.destroy())resolve(false)}})})}}return'nextSuccessor'}//验证:生鲜商品的价格允许高于购买价格productfilefunctionvalidateFreshAllowInPriceHigherThanItemPrice(){//在采购设置中不启用:“允许生鲜商品的价格高于产品文件的采购价格”,则当商品为生鲜商品时,//并且价格高于文件的购买价格,弹框会提示&&item.Price>item.PurcPrice)if(needTip){returnnewPromise((resolve)=>{constmodal=Modal.confirm({title:'提示',content:'采购设置不允许生鲜价格商品要高于商品文件的购买价格,请重新输入价格!',图标:createVNode(ExclamationCircleOutlined),okText:'OK',cancelText:createVNode(),asynconOk(){nextTick(()=>modal.destroy())resolve(false)}})})}}returntrue}//将三个验证函数封装到责任链节点中constvalAmount=newChain(validateAmountMax)constvalCostPrice=newChain(validateInPriceHigherThanAutoPrice)constvalFresh=newChain(validateFreshAllowInPriceHigherThanItemPrice)//指定顺序责任链中的节点数valAmount.setNextSuccessor(valCostPrice).setNextSuccessor(valFresh)//将请求传递给第一个节点returnawaitvalAmount.passRequest()}//保存异步函数save(data){if(!(awaitvalidate(data)))returnfalse//......调用接口保存}