zl程序教程

您现在的位置是:首页 >  前端

当前栏目

[Javascript] Broadcaster + Operator + Listener pattern -- 13. Repeat When Done with a Repeat Operator

JavaScript -- with 13 when pattern Operator listener
2023-09-14 09:00:46 时间

Apps often have scenarios where one event controls another. In operators, this requires passing one broadcaster in and using it to control another broadcaster. You can think, "when this broadcaster fires, do that with the other broadcaster". This lesson covers using one broadcaster to control when another broadcaster repeats.

 

import { addListener, done, forOf } from "./broadcasters";

const log = console.log;

// only when listener receive DONE event
// then broadcaster should trigger the listener again
// otherwise, keep emit value
let repeat = (broadcaster) => (listener) => {
  let cancel;
  let repeatListener = (value) => {
    // when it is doen event
    if (value === done) {
      // because it is repeated event
      // need to cancel previous one
      if (cancel) {
        cancel();
      }
      // broadcaster should trigger the listener again
      cancel = broadcaster(repeatListener);
      return;
    }
    // otherwise, keep emitting value
    listener(value);
  };
  cancel = broadcaster(repeatListener);

  return () => cancel();
};

// Only when 'whenBroadcater' happen then do the repeat logic
let repeatWhen = (whenBroadcaster) => (mainBroadcaster) => (listener) => {
  let mainCancel;
  let whenCancel;
  let repeatListener = (value) => {
    if (value === done) {
      if (mainCancel) {
        mainCancel();
      }
      whenCancel = whenBroadcaster(() => {
       // cancel previous when broadcaster 
        whenCancel();
        mainCancel = mainBroadcaster(repeatListener);
      });
    }
    listener(value);
  };
  mainCancel = mainBroadcaster(repeatListener);

  return () => {
    mainCancel();
    whenCancel();
  };
};

const inputClick = addListener("#input", "click");
const printCat = forOf("cat");
const repeatCatOnClick = repeatWhen(inputClick)(printCat);
const cancel = repeatCatOnClick(log);

setTimeout(() => {
  cancel();
}, 3000);