Skip to content

Instantly share code, notes, and snippets.

@qfox
Created October 25, 2021 19:58
Show Gist options
  • Save qfox/304990146289c28a0fb27e0d8fa2b0a1 to your computer and use it in GitHub Desktop.
Save qfox/304990146289c28a0fb27e0d8fa2b0a1 to your computer and use it in GitHub Desktop.
Continuous effect for effector
import { createEffect, createEvent, Effect, Event } from 'effector';
export interface ContinuousEffect<Params, Done, Payload = Done, Fail = Error> extends Effect<Params, Done, Fail> {
readonly progress: Event<{params: Params; result: Payload}>
readonly progressData: Event<Payload>
}
export function createContinuousEffect<Params, Done, Payload = Done, Fail = Error>(
handler: ((params: Params) => Done | Promise<Done> | Iterator<Payload, Done> | AsyncIterator<Payload, Done>)
) {
const progress = createEvent<{ params: Params, result: Payload }>();
const progressData: Event<Payload> = progress.map({
// @ts-ignore
named: 'progressData',
fn: ({ result }: any) => result,
});
async function continuousHandler(params: Params): Promise<Done> {
let maybeIterator = handler(params);
// Return as is if not iterable
if (!('next' in maybeIterator)) {
return maybeIterator;
}
// Have to use .next manually because for-await-of won't show a final result.
while (true) {
// Can't destructure right here because of typescript troubles
const next = await maybeIterator.next();
if (next.done !== true) {
progress({ params, result: next.value });
} else {
return next.value;
}
}
};
const instance: ContinuousEffect<Params, Done, Payload, Fail> = Object.assign(
createEffect<typeof continuousHandler, Fail>(continuousHandler),
{ progress, progressData },
);
return instance;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment