zoukankan      html  css  js  c++  java
  • [Javascript] Broadcaster + Operator + Listener pattern -- 01

    Let's see the following code first:

    let button = document.getElementById("button");
    button.addEventListener("click", (e) => {
        console.log(e)
    });

    We have a button, which we can attach a event listener to it. In this case, everytime we click on the button, there will be an event broadcasted out.

    So this button event become a "Broadcaster".

    And we have a callback function:

    (e) => {
        console.log(e)
    }

    This is the "Listener", it react to broadcaster event and trigger side effect to the world.

    OK, so far, we have "Broadcaster" and "Listener", let's refactor the code to make it more clear:

    let button = document.getElementById("button");
    let buttonClickBroadcaster = (listener) => {
      button.addEventListener("click", listener);
    };
    let logListener = (value) => {
      console.log(value);
    };
    ButtonClickBroadcaster(logListener)

    We make broadcaster and listener a own function:

    "buttonClickBroadcaster" & "logListener".

    Now if we have requirement that we want logListener log out twice for each button click event. In other word, click button once, there are two logs in the console. How should we do it?

    Well, the first solution come to my mind is modify the listener.

    let logListener = (value) => {
      console.log(value);
      console.log(value);
    };

    We just double the 'console.log', then job is done! 

    Sadly this is not best solution, it has problem:

    We "break" the logListener, it no longer log once, but twice. What if we have other place use this listener? it would break for them as well. So, really, We don't want to touch the existing "Listener", we want to leave it untouched!

    Then how about modify "Broadcaster"? Well, it has the same problem. 

    We modified the existing broadcaster logic, it is not good, we want to keep "Broadcaster" untouched as well!


    Operator

    This is where "Operator" comes in to play. Since we cannot modify "broadcaster" & "listener". We can only introduce a new Role: "Operator".

    So what is Operator?

    [Note]: picture comes from John Lindquist workshop: https://docs.google.com/presentation/d/1-ShMBAImLCv1Pkr7DJ7OPCUPlv9ZMnnEayl8NGrlg5Q/edit#slide=id.g851aa9b068_6_0

    So "Operator", stay between "Broadcaster" & "Listener". 

    And we can chian multi operators together:

    Or even one operator can have multi listeners:

    Or multi broadcasters info one operator:

    So by using "Operator", we can solve the previous problem we have which we want to log out button click event twices.

    How to do that? 

    We create a TwiceOperator, which listen to "Broadcaster", when we got data from "Broadcaster", in "TwiceOperator", we call "Listener" twice.

    let twiceOpertaor = (broadcaser) => (listener) => {
      broadcaser((v) => {
        listener(v);
        listener(v);
      });
    };
    twiceOpertaor(buttonClickBroadcaster)(logListener);

    In this approach, we keep "Listener" & "Broadcaster" untouched, and only modify the value inside "Opeator". This would make code more reuseable and testable.

    FullCode:

    let button = document.getElementById("button");
    let buttonClickBroadcaster = (listener) => {
      button.addEventListener("click", listener);
    };
    let logListener = (value) => {
      console.log(value);
    };
    // opeator give you a chance to re-behavior the listener
    // do whatever changes your want
    let twiceOpertaor = (broadcaser) => (listener) => {
      broadcaser((v) => {
        listener(v);
        listener(v);
      });
    };
    twiceOpertaor(buttonClickBroadcaster)(logListener);

    Summary: 

    Introudce "Operator", we can keep the original "Broadcaster" & "Listener" code unchnaged. And also give us capability to modify the source before the value send to "Listener". 

    So "Operator" takes one or multi "Broadcaster", return a enhacned "Broadcaster"! Similar idea to Typescript decorator, Proxy or React High order component

    And of course, it uses lot of Functional Programming concepts which we will see in the future posts.

  • 相关阅读:
    斗鱼的sidebar的实现简陋的demo
    angular JS中使用jquery datatable添加checkbox点击事件
    angular JS中使用jquery datatable添加ng-click事件
    Redis 中文文档
    操作word的
    Redis作为消息队列服务场景应用案例(入队和出队)
    nopcommerce 商城案例
    net 将手机号码中间的数字替换成星号
    V5客服
    EF 数据库迁移(Migration)
  • 原文地址:https://www.cnblogs.com/Answer1215/p/12884067.html
Copyright © 2011-2022 走看看