在fp-ts中,我试图将一些可能失败的异步任务与TaskEither
链接在一起,但是我需要在链的后面使用中间任务的结果。
在此示例中:
const getFoo = (a: string): Promise<Foo> => {};
const getBar = (foo: Foo): Promise<Bar> => {};
const mkFooBar = (foo: Foo, bar: Bar): Promise<FooBar> => {};
const async main1: Promise<FooBar> => {
const a = "a";
const foo = await getFoo(a);
const bar = await getBar(foo);
const fooBar = await mkFooBar(foo, bar);
return Promise.resolve(fooBar);
};
const main2: Promise<FooBar> => {
const a = "a";
return pipe(
TE.tryCatch(() => getFoo(a), e => e),
TE.chain(foo => TE.tryCatch(() => getBar(foo), e => e)),
TE.chain(bar => TE.tryCatch(() => mkFooBar(??, bar), e => e))
);
};
main1
函数是此问题的async/await
样式解决方案。我想做的是以fp-ts chain
样式模拟类似的内容。 main2
是我的尝试。
由于async/await
版本将所有中间结果引入了本地范围(即foo
和bar
),因此很容易调用mkFooBar
,这取决于这两个结果
但是在fp-ts版本中,中间结果被困在每个任务的范围内。
我认为使该版本工作的唯一方法是使异步函数本身(即getFoo
和getBar
)也返回其参数,或者也许TaskEither
包装器返回了参数,以便可以将其传递给链中的下一个函数。
这将是正确的方法吗?还是有一个更简单的版本更类似于async/await
版本?
答案 0 :(得分:0)
根据在以下计算中需要访问中间结果的次数,我建议您使用Do
from fp-ts-contrib
(Haskell do符号的近似值),或通过手动{ {1}} ping。
给出:
map
import * as TE from "fp-ts/lib/TaskEither";
declare function getFoo(a: string): TE.TaskEither<unknown, Foo>;
declare function getBar(foo: Foo): TE.TaskEither<unknown, Bar>;
declare function mkFooBar(foo: Foo, bar: Bar): TE.TaskEither<unknown, FooBar>;
的示例:
Do
手动映射示例:
import { Do } from "fp-ts-contrib/lib/Do";
function main2(): TE.TaskEither<unknown, FooBar> {
return Do(TE.taskEither)
.bind("foo", getFoo("a"))
.bindL("bar", ({ foo }) => getBar(foo))
.bindL("fooBar", ({ foo, bar }) => mkFooBar(foo, bar))
.return(({ fooBar }) => fooBar);
}