如何解决像 Cats Effect 中的 Chain Fibers在 fp-ts 生态系统中移植到 TypeScript
我正在尝试将 Fiber
从 Scala/Catz 移植到 TypeScript/fp-ts,但遇到了关于如何链接/flatMap 的问题。
(编辑:最终我只是想创建一个可取消的异步 monad,对于 HTTP 请求将使用 axios
,因为这些请求是可取消的。fp-ts
没有可取消的异步,只有不可取消的异步 Task
和 TaskEither
。如果有比这更好的方法,我完全赞成。)
给出总体思路
type Monad<F,E,A> {
chain: <B>(fab: (a:A) => F<E,B>) => (f: F<E,A>) => F<E,B>
}
和Fiber
interface Fiber<E,A> {
cancel: TaskEither<never,void> // TaskEither<A,B> is a typealias for () => Promise<Either<E,A>>
join: TaskEither<E,A>
}
我如何实现 chain
以便
declare const chain: <B>(fab: (a:A) => Fiber<E,B>) => (f: Fiber<E,A>) => Fiber<E,B>
我的第一件事是:
const chain: <E,A,B>(fab: (a:A) => Fiber<E,A>):Fiber<E,B> = ({
cancel: pipe(
fiber.cancel,taskEitherChain(() => fiber.join),taskEitherChain(a => fab(a).cancel)),join: pipe(
fiber.join,taskEitherChain(a => fab(a).join))
})
但这需要我运行 fiber.join
以链接到另一根光纤,以便我可以调用第二根光纤的 cancel
。基本上,要取消第二根光纤,我必须先加入第一根。这给了我
declare fiberThatTakesTenSecondsToComplete: Fiber<string,number>
declare fiberFactory: (i:number) => Fiber<string,boolean>
await pipe(fiberThatTakesTenSecondsToComplete,chain(fiberFactory)).cancel()
最后一行需要 10 秒才能完成,因为 cancel
函数调用了第一个光纤的 .join
。
====
所有这一切的动机是,我为我的 API 使用包装在 TaskEither
类型中的 axios 调用,并且我想结合 axios 的内置功能,以一元方式取消 API 调用。寻找可取消的异步使我找到了 Catz Effect 的 Fiber,这就是我现在所处的位置。
能够取消它们也很有用,因为在 React 应用程序和 useEffect
中,最佳做法是返回一个函数,该函数将取消您在 useEffect
中调用的任何内容。所以像
const MyComponent = () => {
useEffect(() => {
apiFiberThatEventuallyDoesSomethingToTheUI.join()
return apiFiberThatEventuallyDoesSomethingToTheUI.cancel
},[])
}
如果组件在 API 调用仍然很热时卸载,您希望能够取消 API 调用,这样它就不会链接到使用 API 结果更新 UI 的代码部分。
我将 axios 调用与像这样的工厂绑定到 Fiber 中
const axiosGet = (...p: Parameters<typeof axios.get>) => {
const cancelSource = axios.CancelToken.source()
const { token: cancelToken } = cancelSource
return {
cancel: () => {
return taskEitherRight(cancelSource.cancel()) // TaskEither<never,void>
},join: tryCatch(() => axios.get(p[0],{ ...(p[1] ?? {}),cancelToken }),() => 'Error')
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。