提问人:Abraham P 提问时间:9/8/2023 更新时间:9/8/2023 访问量:77
解包任务、处理错误并提供默认值
Unwrapping a task either, handling errors, and providing default value
问:
假设我有一些异步函数,它从 api 获取并返回一个 taskEither(为简单起见,我提供了一个基本的异步任务:
const someAsyncFunction = taskEither.fromPredicate(
(value: number) => value < 12,
(value: number) => new Error("value was greater than 12")
)
然后,如果存在错误,我想将错误报告给哨兵,但是,我希望注入默认值并继续下游执行
const reportError = (error: Error) => console.log(error.message)
type ExceptionHandler = typeof reportError
const unwrapAndReportError = <R>(captureFunction: ExceptionHandler) => (
def: R
) => (inputEither: taskEither.TaskEither<Error, R>): R =>
E.getOrElse((err: Error) => {
captureFunction(err)
return def
})(inputEither)
const runAsyncFunctionThenUnwrapAndReport = flow(
someAsyncFunction,
unwrapAndReportError(reportError)("potato")
)
此代码无法进行类型检查:
Argument of type 'TaskEither<Error, R>' is not assignable to parameter of type 'Either<Error, R>'
完全可运行的示例:https://codesandbox.io/s/fp-ts-playground-forked-dy2xyz?file=/src/index.ts:0-722
我的问题是,如何使用 fp-ts 实现这种效果?这里推荐的模式是什么(以及如何让它进行类型检查)。
答:
1赞
Parker Tailor
9/8/2023
#1
看起来你已经很接近了,应该可以工作,尽管我认为你是从模块中导入的。将其替换为模块中的导入。此外,它使用起来更习惯,因此您可以先提供任一参数。getOrElse
Either
TaskEither
pipe
也许是这样的事情?
import * as TE from "fp-ts/lib/TaskEither"
import * as T from "fp-ts/lib/Task"
import { pipe } from "fp-ts/lib/function"
const someAsyncFunction = TE.fromPredicate(
(value: number) => value < 12,
(value: number) => new Error("value was greater than 12")
)
const reportError = (error: Error) => console.log(error.message)
type ExceptionHandler = typeof reportError
const unwrapAndReportError = <R>(captureFunction: ExceptionHandler) => (
def: R
) => (inputEither: TE.TaskEither<Error, R>): Promise<R> =>
pipe(
inputEither,
TE.getOrElse(
(error) => {
captureFunction(error)
return T.of(def)
},
),
)()
const runAsyncFunctionThenUnwrapAndReport = flow(
someAsyncFunction,
unwrapAndReportError(reportError)("potato")
)
评论
0赞
Abraham P
9/8/2023
我使用折叠来解决这个问题,但这个解决方案实际上似乎更明智,以后可能会返工我的!
0赞
Abraham P
9/8/2023
#2
我最终得到了这个工作:
import { taskEither as TE, function as F, task as T } from 'fp-ts'
const unwrapEitherAndReport = <R>(captureFunction: ExceptionHandler) => (def: R) => (inputEither: TE.TaskEither<Error,R>): T.Task<R>=> F.pipe(
inputEither,
TE.fold(
(err) => {
captureFunction(err)
return T.of(def)
},
T.of
)
)
并使用以下命令运行它:
F.flow(
someAsyncFunction,
unwrapEitherAndReport(handler)('potato')
)
评论