[英]FP-TS: mapping responses
I am using the fp-ts library and I cannot figure out how to implement the following scenario:我正在使用fp-ts库,但我无法弄清楚如何实现以下场景:
{
totalItems: 100,
perPage: 25,
books:[{...}, ...],
....
}
const nrOfPages = Math.ceil(totalItems / perPage);
Now the struggle is that in the end I would like to collect all the books inside one object.现在的斗争是,最后我想收集一本object里面的所有书。 Basically, I want to await the results and flatmap them together.
基本上,我想等待结果并将它们放在一起。 It is also important that the requests should be sequential and use the fp-ts library.
请求应该是顺序的并使用 fp-ts 库也很重要。
const allBooks [{...},{...},{...}, ...];
You can use traverseSeqArray
from the Task
module to map an array of page numbers into tasks to fetch each page, and each task will be executed sequentially.你可以使用
traverseSeqArray
从Task
模块将 map 一个页码数组转换成任务来获取每个页面,并且每个任务会按顺序执行。 Then, you can useconcatAll
(from Monoid
) to concatenate the arrays of books.然后,您可以使用
concatAll
(来自Monoid
)连接书籍的 arrays。
declare const traverseSeqArray: <A, B>(f: (a: A) => Task<B>) => (as: readonly A[]) => Task<readonly B[]>
declare const concatAll: <A>(M: Monoid<A>) => (as: readonly A[]) => A
import * as M from 'fp-ts/lib/Monoid';
import * as RA from 'fp-ts/lib/ReadonlyArray';
import * as T from 'fp-ts/lib/Task';
import {flow, pipe} from 'fp-ts/lib/function';
declare const getBooks: (
shelf: Shelf,
page: number
) => T.Task<{totalItems: number; perPage: number; books: readonly Book[]}>;
const getAllBooks = (shelf: Shelf): T.Task<readonly Book[]> =>
pipe(
// Fetch the first page (assuming pages are zero-indexed)
getBooks(shelf, 0),
T.chain(({totalItems, perPage, books: firstPageBooks}) => {
const nrOfPages = Math.ceil(totalItems / perPage);
// e.g. [1, 2, 3] for 100 books and 25 per page
const pagesToFetch = Array.from(
{length: nrOfPages - 1},
(_, i) => i + 1
);
return pipe(
pagesToFetch,
// With each page...
T.traverseSeqArray(page =>
// ...fetch the books at the page
pipe(
getBooks(shelf, page),
T.map(({books}) => books)
)
),
// Now we have a Task<Book[][]> that we want to turn into
// a Task<Book[]> including the books from the first page
T.map(
flow(
// Prepend the first pages’ books
RA.prepend(firstPageBooks),
// Concatenate the Book[][] into a Book[]
M.concatAll(RA.getMonoid())
)
)
);
})
);
This example assumes that getBooks
does not fail, but tihs can easily be modified by switching out Task
to TaskEither
.此示例假设
getBooks
不会失败,但可以通过将Task
切换到 TaskEither 轻松修改TaskEither
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.