[Javascript Design Mode] responsibility chain mode

Make multiple objects have the opportunity to process the request, so as to avoid the coupling relationship between the sender and receiver of the request, connect these objects into a chain, and pass the request along the chain until an object can process it. These objects in the transmission chain are called nodes.

In practical application, the responsibility chain model is often used in the reconstruction of cumbersome if... if else... Which is similar to the strategy model learned before. Compared with strategy, the responsibility chain model is logically more cumbersome, but the responsibility chain model has greater flexibility.
If the result of the previous link needs to be handed over to the next link to continue processing, then the responsibility chain mode is more suitable for processing at this time.
Next, suppose a requirement

An e-commerce website,
When users pay a 500 deposit and the deposit has been paid, they can enjoy a 500 coupon, which is not limited by the quantity of goods;
When users pay 200 deposit and the deposit has been paid, they can enjoy 500 coupons, which is not limited by the quantity of goods;
When the user does not pay the deposit, it is limited by the quantity of goods. When there is goods, it can be bought at the original price, and when there is no goods, it can not be bought.

var buyOrder = function(orederType, pay, stock){
	if(orederType == 1){
		if(pay){
          console.log('500 coupon');
        } else {
          if(stock > 0){
            console.log('General shopping page');
          } else {
            console.log('Out of stock');
          }
        }
      } else if(orederType == 2){
        if(pay){
          console.log('200 coupon');
        } else {
          if(stock > 0){
            console.log('General shopping page');
          } else {
            console.log('Out of stock');
          }
        }
      } else if(orederType == 3){
        if(stock > 0){
          console.log('General shopping page');
        } else {
          console.log('Out of stock');
        }
      }
}
buyOrder(1, true, 600)

Next, call it

//Three order functions, all of which are node functions
const order500 = function (orderType, pay, stock) {
	if (orderType == '1' && pay == true) {
      console.log('500 coupon');
    } else {
      return 'nextSuccessor';     // No matter who the next node is, it is to pass the request back
   }
}
const order200 = function (orderType, pay, stock) {
	if (orderType == '2' && pay == true) {
		console.log('200 coupon');
	} else {
        return 'nextSuccessor';     // No matter who the next node is, it is to pass the request back
    }
}
const orderNormal = function (orderType, pay, stock) {
	if (stock > 0) {
    	console.log('General shopping page');
	} else {
        console.log('Out of stock');
    }
}
//Wrap the three order functions into the nodes of the responsibility chain
const chainOrder500 = new Chain(order500)
const chainOrder200 = new Chain(order200)
const chainOrderNormal = new Chain(orderNormal)

//Then specify the order of nodes in the responsibility chain
chainOrder500.setNextSuccessor(chainOrder200)
chainOrder200.setNextSuccessor(chainOrderNormal)

//Finally, pass the request to the first node and start the responsibility chain mode
chainOrder500.handleRequest(1, true, 500)     //500 coupons
chainOrder500.handleRequest(3, true, 20)      //General shopping page
chainOrder500.handleRequest(3, true, 0)       //Out of stock

Then let's share another example:
There is an active H5 page, which is used in multiple browser environments, such as wechat, QQ, self-developed apps, other third-party apps, etc. Because the background interface handles different login states in different environments, it is necessary to judge different environments, take different values in cookie s, and transfer different login state token s. Sometimes, there are some special processing for network requests for some special environments.

The following is an example of typescript. You can see that BaseHandler is an abstract class, indicating that it must be attached to another instance

  // Request interceptor responsibility chain node abstract class
export default abstract class BaseHandler {
	// Next node
    private nextHandler: BaseHandler | null = null;
    // Set next node
    public setNextHandler (handler: BaseHandler): BaseHandler {
       this.nextHandler = handler;
       return this.nextHandler;
    }
	// The method of calling the node handles the request, and then calls the next node to continue processing.
    public handleRequest (config: any): void {
       // Processing of current node
       if (this.checkHandler(config)) {
           this.handler(config);
       }
       // Proceed to the next node
       if (this.nextHandler) {
           this.nextHandler.handlerRequest(config);
		}
	}
	// Call the method of the node to process the request. If a node handles the request, it will exit directly (mutually exclusive)
  public handleRequestOnce(config: any): void {
    // Processing of current node
    if (this.checkHandle(config)) {
      this.handler(config);
    } else if (this.nextHandler) {
      this.nextHandler.handleRequestOnce(config);
    }
  }

  // Determine whether to process at this node
  abstract checkHandle(config: any): boolean;
  // Treatment method
  abstract handler(config: any): void;
}
/*

Author: lucio has come to learn all about it
 Link: https://juejin.cn/post/7055149674650402824
 Source: rare earth Nuggets
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.
*/
import BaseHandler from '../../base-handler';
import { getUrlPara } from '../../../url';
import { env } from '../../../env';

// Handle request parameters of H5 embedded in applet
export default class WechatMpParamsHandler extends BaseHandler {
  // In the king's life applet and QQ login, the applet login status is used. In other cases, the wechat login status is used
  checkHandle(): boolean {
    return env.isMiniProgram;
  }
  handler(config: any): any {
    if (getUrlPara('_ticket')) {
      config.params._ticket = getUrlPara('_ticket');
    }
    return config;
  }
}
/*
Author: lucio has come to learn all about it
 Link: https://juejin.cn/post/7055149674650402824
 Source: rare earth Nuggets
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source
*/

Finally, the call is implemented in the axios interceptor

// request interceptor 
const requestInterceptor =  function (config) {
  const requestHandlerChain = new UrlInterceptor(); // Requested responsibility chain node: URL processing of CGI
  requestHandlerChain.setNextHandler(new ParamsInterceptor()); // Requested responsibility chain node: parameter processing of CGI
  requestHandlerChain.handleRequest(config);
  return config;
};

// Response interceptor
const responseInterceptor = (response) => {
  const responseHandlerChain = new ParseDataInterceptor(); // Responsibility chain node of returned data: analyze the data of new and old frameworks
  responseHandlerChain.setNextHandler(new LoginInfoInterceptor()) // Responsibility chain node that returns data: process login information
    .setNextHandler(new ErrorToastInterceptor()); // Responsibility chain node of returned data: handling error prompt
  responseHandlerChain.handleRequest(response);
  return response;
};

// request interceptor 
axiosInstance.interceptors.request.use(requestInterceptor, error => Promise.reject(error));

// Response interceptor
axiosInstance.interceptors.response.use(responseInterceptor, error => Promise.reject(error));
/*
Author: lucio has come to learn all about it
 Link: https://juejin.cn/post/7055149674650402824
 Source: rare earth Nuggets
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.
*/

Above to be continued

Keywords: Javascript Front-end

Added by brandtj on Wed, 23 Feb 2022 12:20:53 +0200