首先,让我们了解什么是Task
真正的东西。
export interface Task<A> {
(): Promise<A>
}
// note that this could also be written as
export type Task<A> = () => Promise<A>
ATask
只是一个返回 a 的函数Promise
,因此在您的示例中调用getHello
将返回 a Promise<string>
。
console.log(getHello())
与 相同console.log(Promise.resolve('hello'))
,因此这就是为什么它会记录类似Promise {<fulfilled>: "hello"}
,Promise<pending>
或其他内容而不是hello
:
// Promise.resolve(foo) is the same as new Promise(resolve => resolve(foo))
const getHello = () => Promise.resolve('hello')
console.log(getHello())
有关 Promises 的更多信息,我建议阅读在 MDN 上使用 Promises。
至于如何用它作曲,因为你Task
可以Monad
使用map
, ap
,chain
等apSecond
。
例如,假设是这样addAtEnd
定义的:
const addAtEnd = (b: string) => (a: string): string => a + b
您可以通过以下getHello()
方式使用它Task.map
:
import * as T from 'fp-ts/Task'
import { pipe } from 'fp-ts/function'
// type of map:
// export declare const map: <A, B>(f: (a: A) => B) => (fa: Task<A>) => Task<B>
// Task<string> which, when called, would resolve to 'hello world'
const getHelloAndAddWorld = pipe(
getHello,
T.map(addAtEnd(' world'))
)
// same as
const getHelloAndAddWorld = T.map(addAtEnd(' world'))(getHello)
或者,如果您想记录它的值,您可以使用chainIOK
and Console.log
:
import * as Console from 'fp-ts/Console'
// type of T.chainIOK:
// export declare function chainIOK<A, B>(f: (a: A) => IO<B>): (ma: Task<A>) => Task<B>
// type of Console.log:
// export declare function log(s: unknown): IO<void>
// Note that IO<A> is a function that (usually) does a side-effect and returns A
// (() => A)
// Task<void>
const logHelloAndWorld = pipe(
getHelloAndAddWorld,
T.chainIOK(Console.log)
)
// same as
const logHelloAndWorld = pipe(
getHello,
T.map(addAtEnd(' world')),
T.chainIOK(Console.log)
)
要执行Task
s,只需调用它:
logHelloAndWorld() // logs 'hello world'
对于函子、应用程序和单子的简单介绍,Adit 的“图片中的函子、应用程序和单子”或Tze-Hsiang Lin 的 JavaScript 版本是一些很好的起点。