Запуск массива TaskEithers параллельно, но продолжайте работу, если не удалось выполнить одну или несколько задач - PullRequest
2 голосов
/ 01 марта 2020

Я должен сделать массив вызовов IO параллельно и объединить содержимое вызова в случае успеха. В случае неудачи другие обрабатываются в обычном режиме, но появляется сообщение об ошибке.

Мой мыслительный процесс о том, как это можно реализовать:

Array<TE<E, A>> -> TE<E, Array<A>> -> TE<E, MergedA> -> [E, A]

Что я ' В настоящее время я делаю:

В настоящее время я секвенирую массив TE, но любой сбой в цепочке приведет к левому.

pipe(
sequenceT(TE.taskEither)(arrayofTE), //TE<E,A>[] -> TE<E,A[]>
TE.map(mergeFn), //TE<E, A[]> -> TE<E, MergedA> 
???
)

Как я могу остановить короткое замыкание?

1 Ответ

3 голосов
/ 01 марта 2020

Вы можете передать T.task вместо TE.taskEither в sequence / sequenceT ( документы ):

Действие: выполнить массив задач параллельно , сбор всех неудач и успехов

TaskEither: array.sequence (T.task) (taskEithers) - то же самое для sequenceT

sequence: параллельное выполнение задач одного типа

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: параллельное выполнение задач другого типа

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>

Вот песочницы с реализацией mergeFn для игры: sequence , sequenceT . Надеюсь, это поможет!

...