Javascript(ES6)可编辑流
是否有一种模式可以使用ES6生成器使流变得可访问 请参阅下面的“MakeStreeamIterable”Javascript(ES6)可编辑流,javascript,stream,iterator,ecmascript-6,Javascript,Stream,Iterator,Ecmascript 6,是否有一种模式可以使用ES6生成器使流变得可访问 请参阅下面的“MakeStreeamIterable” import {createReadStream} from 'fs' let fileName = 'largeFile.txt' let readStream = createReadStream(fileName, { encoding: 'utf8', bufferSize: 1024 }) let myIterableAsyncStream = MakeStreamIte
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的协同程序或与deasync的阻塞不感兴趣
gold是MakeStreamIterable,应该是一个有效函数
是否有一种模式可以使用ES6生成器使流变得可访问
不,这无法实现,因为发电机是同步的。他们必须知道自己在什么时候屈服。异步数据源的迭代目前只能通过使用某种基于回调的实现来实现。因此,如果您所指的是“一个有效函数,其结果可以为循环的的的的一个的一个循环的一个的一个的一个的结果”,那么就没有办法使它成为“一个有效函数”
流是异步的
流表示在可能无限的时间内异步接收的可能无限的数据量。如果我们看一下,我们可以更详细地定义一个流是什么使得它“可联合”:
如果对象知道如何一次访问一个集合中的项,而跟踪其在该序列中的当前位置,则该对象就是迭代器。在JavaScript中,迭代器是一个对象,提供了一个next()方法,该方法返回序列中的下一项。此方法返回具有两个属性的对象:done
和value
(重点是我自己的。)
让我们从这个定义中找出iterable的属性。对象必须
next
,该方法检索具有属性的对象,该属性保存序列中的next值,或通知迭代已完成
for of
可以使用的next
方法),但是我们可以通过使用承诺(耶!)并在闭包中抽象出流的事件处理程序来构建一个假装的接口
// 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))
有关此实现的注意事项:
- 无需立即调用“iterable stream”上的每个
每个
时,调用之前接收到的所有值都会以forEach
-style一个接一个地传递给回调。之后,所有后续数据将立即传递给回调数据收集
,这意味着如果每个
提供的迭代方法不令人满意,我们实际上根本不必调用每个
- 很快您就可以使用。在node 9.8中,您可以通过运行
--harmony
命令行选项来使用它
async function* streamAsyncIterator(stream) {
// Get a lock on the stream
const reader = stream.getReader();
try {
while (true) {
// Read from the stream
const {done, value} = await reader.read();
// Exit if we're done
if (done) return;
// Else yield the chunk
yield value;
}
}
finally {
reader.releaseLock();
}
}
async function example() {
const response = await fetch(url);
for await (const chunk of streamAsyncIterator(response.body)) {
// …
}
}
感谢杰克·阿奇博尔德的上述贡献。2020更新:
看起来流在未来将是“本机”可移植的—只需等待浏览器来实现它:
(流的常量块){
...
}
您如何定义它(什么是数据
…)?一个字节接一个字节(看起来不是这样的)?数据来自readStream。在('data',data=>…)上,我无法找到解决方案。在我看来,这似乎是不可能的。我认为没有co之类的东西,你是不可能做到的。你为什么反对这一点?对于……的
是同步的。不能在异步数据源上同步迭代。有一个关于异步迭代器的建议,但是它被放弃了。很好的抽象。像这样的东西应该是内置的。