Skip to content

Instantly share code, notes, and snippets.

@cowboyd
Created April 10, 2023 17:02
Show Gist options
  • Save cowboyd/50630283916679a316655339d57ffe80 to your computer and use it in GitHub Desktop.
Save cowboyd/50630283916679a316655339d57ffe80 to your computer and use it in GitHub Desktop.
Event Listeners in Effection
import type { Operation, Stream } from "https://esm.sh/effection@3.0.0-alpha.7";
import {
action,
createChannel,
type Resolve,
resource,
suspend,
useScope,
} from "https://esm.sh/effection@3.0.0-alpha.7";
// returns a stream that can be subscribed to for each event.
export function on<T extends Event>(
target: EventTarget,
eventName: string,
): Stream<T, never> {
return resource(function* (provide) {
let { input, output } = createChannel<T, never>();
let scope = yield* useScope();
let dispatch = (event: Event) => {
scope.run(() => input.send(event as T));
};
try {
target.addEventListener(eventName, dispatch);
yield* provide(yield* output);
} finally {
target.removeEventListener(eventName, dispatch);
}
});
}
// an operation that gets the next event from this listener.
export function once<T extends Event>(
target: EventTarget,
eventName: string,
): Operation<T> {
return action<T>(function* (resolve) {
try {
target.addEventListener(eventName, resolve as Resolve<Event>);
yield* suspend();
} finally {
target.removeEventListener(eventName, resolve as Resolve<Event>);
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment