From e74e40eee8b8ebbe5e6943adacbebed1676d1266 Mon Sep 17 00:00:00 2001 From: hyrious Date: Tue, 21 Mar 2023 15:30:09 +0800 Subject: [PATCH] refactor(rtc): add readable() --- packages/agora-rtc-react/src/store.ts | 53 +++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 packages/agora-rtc-react/src/store.ts diff --git a/packages/agora-rtc-react/src/store.ts b/packages/agora-rtc-react/src/store.ts new file mode 100644 index 00000000..6cd8ad3e --- /dev/null +++ b/packages/agora-rtc-react/src/store.ts @@ -0,0 +1,53 @@ +import type { Disposer } from "./utils"; + +/** Callback to inform of a value updates. */ +export type Subscriber = (value: T) => void; + +/** Start and stop notification callbacks. */ +export type StartStopNotifier = (set: Subscriber) => Disposer | void; + +/** Readable interface for subscribing. */ +export interface Readable { + /** + * Subscribe on value changes. + * @param run subscription callback + */ + subscribe(this: void, run: Subscriber): Disposer; +} + +export function readable(value: T, start: StartStopNotifier): Readable { + let stop: Disposer | null | undefined; + const subscribers = new Set>(); + + function set(newValue: T) { + if (!Object.is(value, newValue)) { + value = newValue; + if (stop) { + for (const subscriber of subscribers) { + subscriber(value); + } + } + } + } + + function subscribe(run: Subscriber) { + subscribers.add(run); + if (subscribers.size === 1) { + stop = start(set) || noop; + } + run(value); + return () => { + subscribers.delete(run); + if (subscribers.size === 0 && stop) { + stop(); + stop = null; + } + }; + } + + return { subscribe }; +} + +function noop() { + // noop +}