简体   繁体   English

从分页 API 在 fp-ts 中懒惰地评估递归 stream

[英]Lazily evaluated recursive stream in fp-ts from paginated API

My goal is to request transactions from an API and store them to a database.我的目标是从 API 请求事务并将它们存储到数据库中。 The response is paginated and I want to read every page and store the transactions in batches.响应是分页的,我想读取每一页并分批存储事务。

So for one request/response cycle I wish to then process the result and store it to the database before fetching the next batch.因此,对于一个请求/响应周期,我希望在获取下一批之前处理结果并将其存储到数据库中。

How do I do this in an idiomatic way in fp-ts?我如何在 fp-ts 中以惯用的方式做到这一点? I inject the actual HTTP fetch call as (url:string, init:RequestInit) => TE.TaskEither<Error, Response> in order to keep it testable.我将实际的 HTTP 提取调用注入为(url:string, init:RequestInit) => TE.TaskEither<Error, Response>以使其可测试。

So far I've tested RxJS and fp-ts and that got a bit complicated even if I got it to work.到目前为止,我已经测试了 RxJS 和 fp-ts,即使我让它工作起来也有点复杂。

Did give both recursive function and generators a try but I'm not succeeding in getting it to be lazily evaluated.确实尝试了递归 function 和生成器,但我没有成功地让它被懒惰地评估。

Are there any existing examples with fp-ts that shows a lazily evaluated stream where each element is dependent on the previous?是否有任何现有的 fp-ts 示例显示了一个懒惰评估的 stream ,其中每个元素都依赖于前一个元素?

You can use StateReaderTaskEither .您可以使用StateReaderTaskEither
Let's say you want to read a list of files, and the next filename is stored in the current file.假设您要读取文件列表,并且下一个文件名存储在当前文件中。

import * as TE from 'fp-ts/TaskEither'
import * as RA from 'fp-ts/ReadonlyArray'
import { pipe } from 'fp-ts/function'

const files = {
  file1: 'file2',
  file2: 'file3',
  file3: 'file5',
  file4: 'file6',
  file5: 'file4',
}
const getFile = (filename: string, encoding: string) =>
  Promise.resolve(files[filename])

const fileSRTE: SRTE.StateReaderTaskEither<
  string,
  string,
  unknown,
  string
> = (filename: string) => (encoding: string) =>
  pipe(
    TE.tryCatch(
      () => getFile(filename, encoding),
      (err) => err
    ),
    TE.map((file) => [`file: ${file}`, file])
  )

const fileStream: TE.TaskEither<
  unknown,
  readonly string[]
> = pipe(
  RA.replicate(6, fileSRTE),
  SRTE.sequenceArray,
  SRTE.evaluate('file1')
)('utf-8')

fileStream().then(console.log)
//{ _tag: 'Right',right: [ 'file: file2','file: file3','file: file5','file: file4','file: file6','file: undefined' ] }

You can look more into State and Reader in fp-ts Doc您可以在fp-ts Doc中查看 State 和 Reader 的更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM