typescript - Suoritetaan TaskEither-taulukko rinnakkain, mutta jatketaan, jos yksi tai useampi tehtävä epäonnistuu
Minun täytyy tehdä sarja IO-kutsuja rinnakkain ja yhdistää kutsujen sisältö, jos ne onnistuvat. Jos yksi epäonnistuu, muut käsitellään normaalisti, mutta virheilmoitus annetaan.
Ajatusprosessini siitä, miten tämä voidaan toteuttaa:
Array<TE<E, A>> -> TE<E, Array<A>> -> TE<E, MergedA> -> [E, A]Mitä teen tällä hetkellä:
Sekvensoin parhaillani TE:n taulukkoa, mutta mikä tahansa ketjun epäonnistuminen tuottaa vasemman.
pipe(
sequenceT(TE.taskEither)(arrayofTE), //TE<E,A>[] -> TE<E,A[]>
TE.map(mergeFn), //TE<E, A[]> -> TE<E, MergedA>
???
)
Kuinka voin estää oikosulun?
Vastaus #1
Voit antaa T.task TE.taskEither sijasta sequence/sequenceT -funktioille (dokumentaatio):
Toiminto: suorita joukko tehtäviä rinnakkain, keräten kaikki epäonnistumiset ja onnistumiset
TaskEither: array.sequence(T.task)(taskEithers) - sama kuin sequenceT
sequence: Suoritetaan samantyyppiset tehtävät rinnakkain
import { pipeable as P, taskEither as TE, task as T, array as A, either as E } from "fp-ts";
const arrayofTE: TE.TaskEither<string, number>[] = [
TE.right(1),
TE.right(2),
TE.left("Oh shit")
];
const run = P.pipe(
// change to T.task instead of TE.taskEither here
A.array.sequence(T.task)(arrayofTE),
mergeFn
);
run(); // run side effect
// returns Promise<{"errors":["Oh shit"],"results":[1,2]}>
// whatever merged result you want to have; this one collects all errors and all results
declare function mergeFn(te: T.Task<E.Either<string, number>[]>): T.Task<Results>
type Results = { errors: string[]; results: number[] };
sequenceT: Suoritetaan tehtäviä eri tyypillä rinnakkain
import { apply as AP /* and others above */ } from "fp-ts";
// Here, TaskEither result can be number | boolean (success case), string on error
const arrayofTE = [TE.right(1), TE.right(true), TE.left("Oh shit")] as const;
const run = P.pipe(
AP.sequenceT(T.task)(...arrayofTE), // we use sequenceT here and pass T.task again
mergeFn
);
declare function mergeFn(a: T.Task<E.Either<string, number | boolean>[]>): T.Task<Results>
Tässä on hiekkalaatikoita, joissa on mergeFn-toteutus, joiden kanssa voi leikkiä: sequence, sequenceT.
Vastaus #2
sequenceT fp-ts 2.16.1:n kanssa, jossa TE.taskStream on vanhentunut
import { sequenceT } from "fp-ts/lib/Apply.js"
import * as TE from "fp-ts/lib/TaskEither.js"
await pipe(
sequenceT(TE.ApplyPar)(
checkAuth(event),
getDocs(event),
),
TE.map(([auth, docs]) => {
if (!auth) throw new Error("Unauthorized")
return docs
}),
TE.map(flattenDocs),
)()
