• [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.

  • 相关阅读:
    ps怎么撤销的三种方法和ps撤销快捷键以及连续撤销多步快捷键
    jquery data()
    jQuery.extend方法
    Bootstrap
    骚操作
    mysql作业
    jQuery UI练习
    左侧菜单,表格,认证登录作业
    JS
    js中的DOM操作汇总
  • 原文地址:https://www.cnblogs.com/Answer1215/p/12884067.html
Copyright © 2020-2023  润新知