职责链模式的其他串联方式?
发布于 4 年前 作者 zhsonga 4809 次浏览 来自 问答

在学习javascript设计模式与实践一书中的职责链模式

var order500 = async function( orderType, pay, stock ){ 
	 if ( orderType === 1 && pay === true ){ 
	 	let data = await fetch('http://10.11.4.66:3000/hello',{
					 headers: {
				   'Content-Type': 'application/json;charset=UTF-8',
				 		},
				})
	 			// 	.then(res=>{
					// res.json().then(data=>{
					// 	console.log(data)
					// 	return data
					// })
					// })
				if(data){
					let res = await data.json()
					if(res.data){
						return 'nextSuccessor'
					}
					
				}
	 	
	 }else{ 
	 return 'nextSuccessor'; // 我不知道下一个节点是谁,反正把请求往后面传递
	 } 
}; 
var order200 = function( orderType, pay, stock ){ 
	 if ( orderType === 2 && pay === true ){ 
	 console.log( '200 元定金预购,得到 50 优惠券' ); 
	 }else{ 
	 return 'nextSuccessor'; // 我不知道下一个节点是谁,反正把请求往后面传递
	 } 
}; 
var orderNormal = function( orderType, pay, stock ){ 
	 if ( stock > 0 ){ 
	 console.log( '普通购买,无优惠券' ); 
	 }else{ 
	 console.log( '手机库存不足' ); 
	 } 
};

function Aop(){

}
//  连接职责节点
Function.prototype.after =  function( fn ){  
	 var self = this;    // js中一切都是对象 function也是对象 所以this可以指向fun
	 return async function(){ 
    	 var ret = await self.apply( this, arguments ); 
    	 if ( ret === 'nextSuccessor' ){ 
    	 return fn.apply( this, arguments ); 
    	 } 
    	 // return ret; 
	 } 
}; 
var order = order500.after( order200 ).after( orderNormal );
order( 1, true, 500 ); // 输出:500 元定金预购,得到 100 优惠券
order( 2, true, 500 ); // 输出:200 元定金预购,得到 50 优惠券
order( 1, false, 500 ); // 输出:普通购买,无优惠券 

为了更贴近业务增加了异步请求,又觉得Function.prototype.after 直接在Function的原型链上做了修改可能不太好, 然后有了两个想法 1.在每个职责方法的prototype上添加after方法 但是觉得很麻烦 2.让每个职责方法继承同一个方法的原型 但是并不能像new 出来的object那样操作原型链(或者说我并不知道该怎么操作) 书中还有个通过类实现的方法 也比较繁琐

想问一下大佬们有什么好的实现方法或者思路吗

后续实现

将问题转化成了多个异步按顺序执行 并且根据结果判断是否继续执行

// 带有异步的职责链模式

   var order500 = async function (orderType, pay, stock) {
      if (orderType === 1 && pay === true) {
        let data = await fetch('http://10.11.4.66:3000/hello', {
          headers: {
            'Content-Type': 'application/json;charset=UTF-8',
          },
        })
        // 	.then(res=>{
        // res.json().then(data=>{
        // 	console.log(data)
        // 	return data
        // })
        // })
        if (data) {
          let res = await data.json()
          if (res.data) {
            console.log("500")
            return '1'
          }

        }

      } else {
        return 'nextSuccessor'; // 我不知道下一个节点是谁,反正把请求往后面传递
      }
    };
    var order200 = async function (orderType, pay, stock) {
      if (orderType === 2 && pay === true) {
        console.log('200 元定金预购,得到 50 优惠券');
      } else {
        return 'nextSuccessor'; // 我不知道下一个节点是谁,反正把请求往后面传递
      }
    };
    var orderNormal = async function (orderType, pay, stock) {
      if (stock > 0) {
        console.log('普通购买,无优惠券');
      } else {
        console.log('手机库存不足');
      }
    };

    function Chain(...fn) {
      console.log(fn)
      this.fn = fn
    }
    Chain.prototype.do = function (...args) {
      let start = 0 
      if (start > this.fn.length || start < 0) return; // 参数start不能超过    arr.length,不能为负数
      let next = (i) => {
        if (i < this.fn.length) {
          let fn = this.fn[i];  // 所以每个职责节点必须返回promis  也可以判断类型是不是promise做一下兼容没有返回promise的情况?
          fn(...args).then(res => {
            // console.log(res);
            if (res == 'nextSuccessor') {
              i++;
              next(i)
            }

          })
        }
      }
      next(start)
      return this
    }
    new Chain(order500, order200, orderNormal).do(1, true, 500).do(2, true, 500).do(1, false, 500 )

每个chain对象都是一条职责链 根据传入的方法顺序进行执行

5 回复
function Chain(arg) {
  this.value = arg
}
Chain.prototype.add = function (func) {
  this.value = func(this.value)
  return this
}
Chain.prototype.valueOf = function() {
  return this.value
}

new Chain(data).
    add(dataMsg).
    add(dataFormat).
    add(listFormat).
    valueOf()

@teenth 谢谢 受你的启发又写了一个出来 包含异步的话函数执行的顺序是会变的

@zhsonga 异步可以使用 promise 使用resolve

@teenth add中有异步的话Chain(data).add(dataMsg).add(dataFormat).add(listFormat).valueOf()这种链式的调用方式会出问题

@zhsonga 这个肯定得改

回到顶部