관찰자 모델의 프로젝트 실천

3910 단어

업무 장면


프로젝트는 단일 페이지 웹 응용 프로그램으로 서버와 통신하는 데 사용되는 웹 소켓 서비스가 있습니다.처음에는 주로 두 가지 작용이 있었다.
  • 계정이 중복 로그인을 방지합니다.계정이 다른 곳에서 로그인할 때 웹소켓은 서버 메시지를 받고 사이트는 즉시 창에 사용자에게'현재 계정은 다른 곳에서 로그인합니다'라고 알려준다. 그리고 사이트는 로그인 정보를 지우고 로그인 페이지로 이동한다.
  • 배달 관리 인터페이스를 열 때 새로운 배달 요청이 있으면 웹socket에서 서버 메시지를 받고 사용자에게 "새로운 배달 요청이 있습니다. 제때에 처리하십시오."라고 알립니다.배송 관리 인터페이스를 열지 않으면 알림이 표시되지 않습니다.

  • 처음에는 이렇게 이루어졌다.
    //BasciWebsocket.js
     websocket.onmessage = function (event) {
       try{
            let {data} = event;
            let _data = JSON.parse(data);
            switch(_data.type){
              case 100:
                Modal.warning({
                  title: ' ',
                  content: " , 。 , 。",
                  okText: ' ',
                  onOk: ()=> {
                    tool.clearUserCookie();
                    window.location = "/login";
                  }
                });
                break;
              case 101:
                let isPageShow = tool.ifDeliveryPageShow();
                if(isPageShow){
                   // “ , ”
                }
                break;
            }
          }catch(e){
    
          }
     };
    

    보아하니 아무런 문제가 없는 것 같다.그러나 프로젝트가 갈수록 복잡해지면서 웹소켓이 알림을 맡는다는 소식도 풍부해지고 있다.메시지를 받은 후에 종종 구체적인 페이지 표현을 바꾸어야 하기 때문에 구체적인 페이지와 관련성이 매우 크다.예를 들어 사용자가 주문 상세 페이지에 머물 때 새로운 주문 피드백을 받으면 주문 상세 페이지의 평론 목록 구역에 새로운 피드백 정보가 애니메이션으로 나와야 한다.
    이럴 때 구체적인 페이지의 강도와 관련된 논리를 기초적인 BasciWebsocket.js 파일에 쓰는 것은 과학적이지 않고 BasciWebsocket.js 비대해져서 유지하기가 좀 힘들다는 것을 알게 될 것이다.문제는 기본적인 웹소켓 서비스와 모든 페이지의 메시지 처리 논리가 결합되지 않는다는 데 있다.
    어렵지 않게 알 수 있듯이 이 업무 장면에서 웹소켓 서비스는 사실 하나의 정보 발표자이고 이런 구체적인 페이지는 정보 구독자이다.자연스레 나는 생명의 볏짚인 고전적인 발표-구독 모드(관찰자 모드라고도 부른다)를 생각했다.

    관찰자 모드


    관찰자 모드는 대상 간의 일대다 의존 관계를 정의합니다. 대상의 상태가 바뀌면 모든 의존 대상이 알림을 받습니다.
    어떻게 관찰자 모델을 실현합니까?
  • 발표자(websocket 서비스)를 맡을 사람을 지정한다.
  • 게시자에게 캐시 목록을 추가하여 리셋 함수를 저장하여 구독자에게 알릴 수 있도록 합니다(구체적인 페이지).
  • 발표자가 대외적으로 정보 구독/구독 취소 방법을 제공하는 것은 실질적으로 캐시 목록의 내용을 바꾸는 것이다.
  • 메시지를 발표할 때 발표자는 이 캐시 목록을 훑어보고 안에 저장된 구독자 리셋 함수를 터치합니다.

  • 실천


    우선BasciWebsocket.js을 정보 발표자로 변신:
    export default class BasicWebsocket{
    
      constructor() {
        if(typeof BasicWebsocket.instance === 'object') {
          return BasicWebsocket.instance;
        }
        // 
        this.listeners = {};
        this.init();
        
        BasicWebsocket.instance = this;
      }
    
      // 
      addListener = (key,func)=>{
         this.listeners[key] = func;
      };
    
      // 
      removeListener = (key)=>{
         delete this.listeners[key];
      };
    
    
      init = ()=>{
        // websocket , 
        let websocket = this.getWebsocket(); 
    
        let that = this;
        // websocket 
        websocket.onmessage = function (event) {
          try{
            let {data} = event
            let _data = JSON.parse(data);
            // ,  
            let keys = Object.keys(that.listeners);
            for(let i = 0,j = keys.length; i < j; i++){
              let func = that.listeners[keys[i]];
              func(_data);
            }
          }catch(e){
    
          }
        };
      };
      
      // 
    }
    

    그리고 발송 관리 페이지에 불러올 때 발송 메시지를 구독할 수 있습니다.배송 관리 페이지를 마운트 해제할 때 메시지를 취소합니다.다른 페이지는 이렇게 유추한다.
    class Distribution extends Component{
      //  
      constructor(props) {
        super(props);
        //  
        this.state = {
          newCount:0
        };
        this.websocket = new BasicWebsocket();
      }
    
      // 
      componentDidMount() {
        let that = this; 
        // 
        this.websocket.addListener("distribution",(d)=>{
          if(d.type == 101){
            that.showNotification(); // “ , ”
            // 
            let {count} = d.data;
            let count = that.state.newCount + count;
            that.setState({
              newCount:count
            });
          }
        });
      }
    
      // 
      componentWillUnmount() {
        // 
        this.websocket.removeListener("distribution");
      }
    }
    

    이로써 관찰자 모델을 통해 기초적인 웹소켓 서비스와 구체적인 페이지 논리의 결합을 실현하고 코드의 유지보수성을 향상시켰다.

    좋은 웹페이지 즐겨찾기