Created
October 25, 2021 19:58
-
-
Save qfox/304990146289c28a0fb27e0d8fa2b0a1 to your computer and use it in GitHub Desktop.
Continuous effect for effector
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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