fp-ts, sequenceT 및 달콤한 달콤한 비동기 유형 FP
15597 단어 iotstypescriptfptsfunctional
const tasks = [task.of(1), task.of(2)]
array
.sequence(task)(tasks)()
.then(console.log) // [ 1, 2 ]
흠. 꽤 좋은데 유형이 다르면 어떻게 됩니까?
const tasks = [T.task.of(1), T.task.of("hello")]
array
.sequence(task)(tasks)()
.then(console.log) // [1, "hello"] I hope?
어 오.
젠장.
sequence
의 유형은 (단순화된) Array[F[A]] => F[Array[A]]
이므로 모든 반환 유형이 동일해야 합니다.무엇을? :/
약간의 구글 검색 후 마법의 sequenceT을 발견했습니다.
/**
* const sequenceTOption = sequenceT(option)
* assert.deepStrictEqual(sequenceTOption(some(1)), some([1]))
* assert.deepStrictEqual(sequenceTOption(some(1), some('2')), some([1, '2']))
* assert.deepStrictEqual(sequenceTOption(some(1), some('2'), none), none)
*/
멋진! 좋아, 한번 해 보자.
import * as T from 'fp-ts/lib/Task'
import { sequenceT } from 'fp-ts/lib/Apply'
import { pipe } from 'fp-ts/lib/pipeable'
pipe(
sequenceT(T.task)(T.of(42), T.of("tim")), //[F[A], F[B]] => F[A, B]
T.map(([answer, name]) => console.log(`Hello ${name}! The answer you're looking for is ${answer}`))
)();
Hello tim! The answer you're looking for is 42
글쎄요.
pipe
를 사용하면 호출을 함께 연결할 수 있으므로 sequenceT
의 결과가 T.map
로 전달됩니다. T.map
는 튜플을 분해하고 데이터에 대한 몇 가지 보증을 통해 원하는 대로 할 수 있습니다. 하지만 작업이 실패할 수 있다면 어떻게 될까요?pipe(
sequenceT(TE.taskEither)(TE.left("no bad"), TE.right("tim")),
TE.map(([answer, name]) => console.log(`Hello ${name}! The answer you're looking for is ${answer}`)),
TE.mapLeft(console.error)
)();
no bad
대박! 좋아, 멋져질 시간이야. 실제로 API를 호출하고 API에서 얻은 결과가 예상 스키마를 준수하는지 확인하려면 어떻게 해야 할까요?
편리한 http 클라이언트인
axios
로 더미 REST 끝점을 쳐서 사용해 봅시다.import { array } from 'fp-ts/lib/Array'
import axios, { AxiosResponse } from 'axios';
import * as t from 'io-ts'
//create a schema to load our user data into
const users = t.type({
data: t.array(t.type({
first_name: t.string
}))
});
//schema to hold the deepest of answers
const answer = t.type({
ans: t.number
});
//Convert our api call to a TaskEither
const httpGet = (url:string) => TE.tryCatch<Error, AxiosResponse>(
() => axios.get(url),
reason => new Error(String(reason))
)
/**
* Make our api call, pull out the data section and decode it
* We need to massage the Error type, since `decode` returns a list of `ValidationError`s
* We should probably use `reporter` to make this nicely readable down the line
*/
const getUser = pipe(
httpGet('https://reqres.in/api/users?page=1'),
TE.map(x => x.data),
TE.chain((str) => pipe(
users.decode(str),
E.mapLeft(err => new Error(String(err))),
TE.fromEither)
)
);
const getAnswer = pipe(
TE.right(42),
TE.chain(ans => pipe(
answer.decode({ans}),
E.mapLeft(err => new Error(String(err))),
TE.fromEither)
)
)
/**
* Make our calls, and iterate over the data we get back
*/
pipe(
sequenceT(TE.taskEither)(getAnswer, getUser),
TE.map(([answer, users]) => array.map(users.data, (user) => console.log(`Hello ${user.first_name}! The answer you're looking for is ${answer.ans}`))),
TE.mapLeft(console.error)
)();
Hello George! The answer you're looking for is 42
Hello Janet! The answer you're looking for is 42
Hello Emma! The answer you're looking for is 42
Hello Eve! The answer you're looking for is 42
Hello Charles! The answer you're looking for is 42
Hello Tracey! The answer you're looking for is 42
그래! 우리는 해냈다! 모두를 위한 비동기식 FP! :)
Reference
이 문제에 관하여(fp-ts, sequenceT 및 달콤한 달콤한 비동기 유형 FP), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/gnomff_65/fp-ts-sequencet-and-sweet-sweet-async-typed-fp-5aop텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)