[Javascript] Broadcaster + Operator + Listener pattern -- 12. Repeat a broadcaster that is DONE

After a broadcaster is "done", starting it up again requires calling the broadcaster with the same listener. This creates a kind of "async recursion" where you pass the listener back into the broadcaster each time you set it up. This lesson walks through creating a repeat operator that can start a broadcaster over.

Idea for Repeat operator, is that when source broadcaster emit done, then in repeat operator call the broadcaster(repeatListener) again.

 

let repeat = (broadcaster) => (listener) => {
  let cancel;
  let repeatListener = (value) => {
    if (value === done) {
      if (cancel) {
        cancel();
      }
      cancel = broadcaster(repeatListener);
      return;
    }

    listener(value);
  };
  cancel = broadcaster(repeatListener);

  return () => {
    cancel();
  };
};

 


import { createTimeout, done } from "./broadcasters";
import { hardCode } from "./operators";

let repeat = (broadcaster) => (listener) => {
  let cancel;
  let repeatListener = (value) => {
    if (value === done) {
      if (cancel) {
        cancel();
      }
      cancel = broadcaster(repeatListener);
      return;
    }

    listener(value);
  };
  cancel = broadcaster(repeatListener);

  return () => {
    cancel();
  };
};

let one = repeat(hardCode("hi")(createTimeout(1000)));

let cancel = one(console.log);
setTimeout(() => {
  cancel();
}, 5000);


// broadcasters.js
import { curry } from "lodash"
export let done = Symbol("done")

export let createTimeout = curry((time, listener) => {
  let id = setTimeout(() => {
    listener(null)
    listener(done)
  }, time)

  return () => {
    clearTimeout(id)
  }
})


// operators.js
import { curry } from "lodash";
import { done } from "./broadcasters";

let createOperator = curry((operator, broadcaster, listener) => {
  return operator((behaviorListener) => {
    return broadcaster((value) => {
      if (value === done) {
        listener(done);
        return;
      }

      behaviorListener(value);
    });
  }, listener);
});

export let hardCode = (newValue) =>
  createOperator((broadcaster, listener) => {
    let cancel = broadcaster((value) => {
      listener(newValue);
    });

    return () => cancel();
  });

  

posted @ 2020-11-03 01:22  Zhentiw  阅读(83)  评论(0编辑  收藏  举报