Skip to content

Commit

Permalink
async notifier
Browse files Browse the repository at this point in the history
  • Loading branch information
ludvigalden committed Jan 10, 2022
1 parent eb1e201 commit 4026b95
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
49 changes: 49 additions & 0 deletions src/notifier-async.ts
@@ -0,0 +1,49 @@
import { AsyncChangeListener, UnsubscribeFn } from "./types";

export class NotifierAsync<T> extends Set<AsyncChangeListener<T>> {
subscribe(listener: AsyncChangeListener<T>): UnsubscribeFn {
this.add(listener);

return () => this.unsubscribe(listener);
}

unsubscribe(listener: AsyncChangeListener<T>) {
this.delete(listener);
}

notify(value: T): void | Promise<void>;
notify(value: T, ...otherArgs: any[]): void | Promise<void>;
notify(...args: any[]): void | Promise<void> {
const promises: Promise<void>[] = [];
Array.from(this.values()).forEach((listener) => {
const promiseOrVoid = listener(...(args as [T]));
if (isPromise(promiseOrVoid)) {
promises.push(promiseOrVoid);
}
});
if (promises.length) {
return Promise.all(promises).then(() => {});
}
}

static get<T>(abon: any): NotifierAsync<T> {
return (abon as any)[KEY];
}

static define<T>(abon: T): T {
Object.defineProperty(abon, KEY, {
value: new NotifierAsync(),
configurable: false,
writable: false,
enumerable: false,
});

return abon;
}
}

const KEY = "__notifier";

function isPromise(v: any): v is Promise<any> {
return Boolean(v && typeof v["then"] === "function");
}
4 changes: 4 additions & 0 deletions src/types.ts
Expand Up @@ -38,3 +38,7 @@ export type SubscriberFlexResult = UnsubscribeFn | boolean | undefined | null |
export type ComposedSubscriberFlexResult = SubscriberFlexResult | Iterable<SubscriberFlexResult>;

export type ComposedSubscriberFlex = (listener: () => void) => ComposedSubscriberFlexResult;

export interface AsyncChangeListener<T> {
(current: T): void | Promise<void>;
}

0 comments on commit 4026b95

Please sign in to comment.