我有一个场景,我的制作人比我的消费者运行的速度要快很多。但是,我不想阻止制作人。所以唯一的选择是通过文件缓冲额外的数据。
我设法制作了一个非最佳解决方案。但是,必须有一种更务实的方式来实现这一点。
我更熟悉RxJS,我可能不会遇到太多问题,但我刚刚开始转向高地,并希望得到一些建议。
import fs from 'fs-promise'
import _ from 'highland'
export default function buffer(id, source) {
const ctx = {
fd: null,
written: 0,
read: 0,
eof: false,
err: null,
path: `/tmp/${id}`
}
async function drain(push) {
ctx.fd = ctx.fd || await fs.open(ctx.path, 'w+')
const bufferSize = 1024 * 1024
while (ctx.read < ctx.written) {
let buffer = new Buffer(bufferSize)
buffer = buffer.slice(0,
await fs.read(ctx.fd, buffer, 0, buffer.length, ctx.read))
if (buffer.length === 0) {
break
}
ctx.read += buffer.length
push(null, buffer)
}
}
// TODO: What about errors?
source.each(async (x) => {
try {
ctx.fd = ctx.fd || await fs.open(ctx.path, 'w+')
if (x === _.nil) {
ctx.eof = true
} else {
ctx.written += await fs.write(ctx.fd, x, 0, x.length, ctx.written)
}
} catch (err2) {
ctx.err = err2
}
})
return _(async (push, next) => {
try {
await drain()
if (ctx.err) {
throw ctx.err
} else if (ctx.eof) {
await drain()
fs.unlink(ctx.path)
push(null, _.nil)
} else {
setTimeout(next, 40)
}
} catch (err2) {
fs.unlink(ctx.path)
push(err2)
}
})
}