草庐IT

Javascript (ES6) 可迭代流

coder 2024-07-15 原文

是否有使用 ES6 生成器使流可迭代的模式?

请参阅下面的“MakeStreamIterable”。

import {createReadStream} from 'fs'

let fileName = 'largeFile.txt'
let readStream = createReadStream(fileName, {
  encoding: 'utf8',
  bufferSize: 1024
})
let myIterableAsyncStream = MakeStreamIterable(readStream)

for (let data of myIterableAsyncStream) {
  let str = data.toString('utf8')
  console.log(str)
}

我对co 或 bluebird 的coroutine 或使用deasync 阻塞不感兴趣。

金子是 MakeStreamIterable 应该是一个有效的函数。

最佳答案

Is there a pattern for making a stream iterable using ES6 generators?

不,这无法实现,因为生成器是同步的。他们必须知道他们在什么时候产出什么。异步数据源的迭代目前只能通过使用某种基于回调的实现来实现。因此,如果您的意思是“一个有效函数,其结果可以提供给 for-of 循环,则无法使 MakeStreamIterable 成为“有效函数” '.

流是异步的

流表示在可能无限的时间内异步接收的可能无限量的数据。如果我们看一下 definition of an iterator on MDN我们可以更详细地定义什么是使流“可统一”的流:

An object is an iterator when it knows how to access items from a collection one at a time, while keeping track of its current position within that sequence. In JavaScript an iterator is an object that provides a next() method which returns the next item in the sequence. This method returns an object with two properties: done and value.

(重点是我自己。)

让我们从这个定义中挑选出可迭代对象的属性。该对象必须...

  1. 知道如何一次访问一个集合中的项目;
  2. 能够跟踪其在数据序列中的当前位置;
  3. 并提供一个方法 next,该方法检索一个对象,该对象的属性包含序列中的下一个,或者通知迭代完成.

流不符合上述任何条件,因为...

  1. 它无法控制何时它接收数据并且无法“展望 future ”以找到下一个值;
  2. 它无法知道何时或是否已收到所有数据,只有在流关闭时才知道;
  3. 并且它没有实现 iterable protocol因此不会公开 for-of 可以使用的 next 方法。

______

伪造它(eration)

我们不能实际上迭代从流中接收到的数据(绝对不是使用for-of),但是我们可以构建一个假装的接口(interface) 通过使用 Promises(耶!)并在闭包中抽象出流的事件处理程序。

// MakeStreamIterable.js
export default function MakeStreamIterable (stream) {
  let collection = []
  let index = 0
  let callback
  let resolve, reject

  stream
    .on('error', err => reject && reject(err))
    .on('end', () => resolve && resolve(collection))
    .on('data', data => {
      collection.push(data)

      try {
        callback && callback(data, index++)
      } catch (err) {
        this.end()
        reject(err)
      }
    })

  function each (cb) {
    if(callback) {
      return promise
    }

    callback = (typeof cb === 'function') ? cb : null

    if (callback && !!collection) {
        collection.forEach(callback)
        index = collection.length
    }

    return promise
  }

  promise = new Promise((res, rej) => {
    resolve = res
    reject = rej
  })

  promise.each = each

  return promise
}

我们可以这样使用它:

import {MakeStreamIterable} from './MakeStreamIterable'

let myIterableAsyncStream = MakeStreamIterable(readStream)

myIterableAsyncStream
  .each((data, i) => {
    let str = data.toString('utf8')
    console.log(i, str)
  })
  .then(() => console.log('completed'))
  .catch(err => console.log(err))

关于此实现的注意事项:

  • 不必立即在“可迭代流”上调用each
  • each 被调用时,在其调用之前接收到的所有值都被一个接一个地传递给回调 forEach 风格。之后,所有后续数据都会立即传递给回调。
  • 该函数返回一个 Promise,它在流结束时解析完整的数据集合,这意味着我们实际上根本不需要调用 each each 提供的迭代并不令人满意。
  • 我培养了将其称为迭代器的错误语义,因此我是一个糟糕的人。请向有关当局举报我。

关于Javascript (ES6) 可迭代流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32902139/

有关Javascript (ES6) 可迭代流的更多相关文章

  1. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  2. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  3. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

  4. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  5. ruby - 迭代在 Ruby 中是如何工作的? - 2

    我最近开始编写Ruby代码,但我对block参数有误解。以下面的代码为例:h={#Ahashthatmapsnumbernamestodigits:one=>1,#The"arrows"showmappings:key=>value:two=>2#ThecolonsindicateSymbolliterals}h[:one]#=>1.Accessavaluebykeyh[:three]=3#Addanewkey/valuepairtothehashh.eachdo|key,value|#Iteratethroughthekey/valuepairsprint"#{value}:#{ke

  6. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  7. ruby - 从特定索引开始迭代数组 - 2

    我想从特定索引开始遍历数组。我该怎么做?myj.eachdo|temp|...end 最佳答案 执行以下操作:your_array[your_index..-1].eachdo|temp|###end 关于ruby-从特定索引开始迭代数组,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/44151758/

  8. ruby - 如何使用每个迭代器获取数组索引或迭代次数? - 2

    我正在用ruby​​遍历一个数组。有没有一种简单的方法可以在不返回for循环的情况下获取迭代次数或数组索引? 最佳答案 啊,知道了。each_with_index哇!编辑:糟糕! 关于ruby-如何使用每个迭代器获取数组索引或迭代次数?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/706115/

  9. ruby - Ruby中的高阶迭代器? - 2

    我在阅读有关.each迭代器的Ruby问题,有人说如果更高阶的迭代器更适合该任务,则使用.each可能会产生代码味道。Ruby中的高阶迭代器是什么?编辑:我提到的StackOverflow答案的作者JörgWMittag提到他是要编写更高级别的迭代器,但他还解释了下面的内容。 最佳答案 哎呀。我的意思是更高级别的迭代器,而不是更高阶的迭代器。当然,每个迭代器都是高阶的。基本上,迭代是一个非常低级的概念。编程的目的是与团队中的其他利益相关者交流意图。“初始化一个空数组,然后遍历另一个数组,并将该数组的当前元素添加到第一个数组中(如果该

  10. javascript - jQuery 的 jquery-1.10.2.min.map 正在触发 404(未找到) - 2

    我看到有关未找到文件min.map的错误消息:GETjQuery'sjquery-1.10.2.min.mapistriggeringa404(NotFound)截图这是从哪里来的? 最佳答案 如果ChromeDevTools报告.map文件的404(可能是jquery-1.10.2.min.map、jquery.min.map或jquery-2.0.3.min.map,但任何事情都可能发生)首先要知道的是,这仅在使用DevTools时才会请求。您的用户不会遇到此404。现在您可以修复此问题或禁用sourcemap功能。修复:获取文

随机推荐