用于将块写入文件的事件驱动模式 - JS
event driven pattern for writing chunks to a file - JS
我正在尝试通过 WebRTC 传输文件,并且我正在努力寻找一种在数据传入时写入数据的良好模式。由于文件块将以未知速率传入,我需要能够在每个块可用时编写它;这意味着两件事:
- 如果数据进来的速度太快,那么我们需要在当前写入任务完成后将每个块排队等待写入
- 如果数据进来的速度太慢,那么我们需要等待块变得可用
理想情况下,我想避免依赖 setTimeout()
来等待块到达。到目前为止我所拥有的很接近,但不完全是我正在寻找的:
// container to hold chunks as they come in
var chunkCollection = {};
// callback function for RTCDataChannel messages
function onData(data) {
chunkCollection[data.chunkIndex] = data.chunk;
writeToFile(data.chunkIndex);
}
function writeToFile(chunkIndexToWrite) {
// if we have the next chunk, write it to the file
if (chunkCollection[chunkIndexToWrite]) {
var chunk = chunkCollection[chunkIndexToWrite];
delete chunkCollection[chunkIndexToWrite];
fileWriter.seek(chunk.offset);
fileWriter.write(chunk.blob);
}
else {
// we don't have the next chunk, so we have to wait
setTimeout(function() {
writeToFile(chunkIndexToWrite);
}, 100);
}
}
这样做的问题是,如果块进入的速度太快,fileWriter
将不会准备好写入下一个块,并会抛出异常。但是,如果块进来太慢,设置正确的超时时间将非常棘手。
似乎事件驱动的方法在这里最有效。一个事件是来自 RTCDataChannel
的数据消息。另一个事件是 fileWriter
已经完成写入,准备写入下一个块。但是我遇到的问题是如何正确地等待一个块进来...
如果浏览器不忙于写入文件,而只是等待块进入,那么浏览器应该在块可用时立即开始写入块。但是如果没有丑陋的 setTimeout
循环,我无法弄清楚如何做到这一点;想不通怎么发个活动说不用等了,可以继续写了。
执行此操作的最佳模式是什么?
有一种方法可以在不超时的情况下做到这一点,虽然它使用标志来指示写入器可用,但它仍然比超时循环更好。
我会创建一个队列,当数据块到达时将存储在该队列中,并使用异步 fileWriter(当它完成写入文件时执行回调)。
像那样:
var readyToWrite = true;
var chunks = [];
var onData = function(data) {
chunks.push(data);
if (readyToWrite) {
writeChunksToFile(chunks);
}
};
var writeChunksToFile = function() {
if (chunks) {
readyToWrite = false;
fileWriter.write(chunks.shift(), function() {
writeChunksToFile(chunks);
});
} else {
readyToWrite = true;
}
};
这样 writer 一直写到 chunks 变空,然后它通知数据接收者(使用标志)它可用,所以数据接收器 (onData) 知道它必须在接收到下一个块时再次调用它。如果数据接收者获取数据并且 writer 仍在写入文件,那么它不会调用它,它只会将块推送到我们的队列数组,写入器将在完成时获取该块他的写作,因为它是递归调用的。
这是我们可以使用该方法编写的最简单的代码,但是您可以使用 ObserverPattern 或 "more functional" 使用 单子.
我正在尝试通过 WebRTC 传输文件,并且我正在努力寻找一种在数据传入时写入数据的良好模式。由于文件块将以未知速率传入,我需要能够在每个块可用时编写它;这意味着两件事:
- 如果数据进来的速度太快,那么我们需要在当前写入任务完成后将每个块排队等待写入
- 如果数据进来的速度太慢,那么我们需要等待块变得可用
理想情况下,我想避免依赖 setTimeout()
来等待块到达。到目前为止我所拥有的很接近,但不完全是我正在寻找的:
// container to hold chunks as they come in
var chunkCollection = {};
// callback function for RTCDataChannel messages
function onData(data) {
chunkCollection[data.chunkIndex] = data.chunk;
writeToFile(data.chunkIndex);
}
function writeToFile(chunkIndexToWrite) {
// if we have the next chunk, write it to the file
if (chunkCollection[chunkIndexToWrite]) {
var chunk = chunkCollection[chunkIndexToWrite];
delete chunkCollection[chunkIndexToWrite];
fileWriter.seek(chunk.offset);
fileWriter.write(chunk.blob);
}
else {
// we don't have the next chunk, so we have to wait
setTimeout(function() {
writeToFile(chunkIndexToWrite);
}, 100);
}
}
这样做的问题是,如果块进入的速度太快,fileWriter
将不会准备好写入下一个块,并会抛出异常。但是,如果块进来太慢,设置正确的超时时间将非常棘手。
似乎事件驱动的方法在这里最有效。一个事件是来自 RTCDataChannel
的数据消息。另一个事件是 fileWriter
已经完成写入,准备写入下一个块。但是我遇到的问题是如何正确地等待一个块进来...
如果浏览器不忙于写入文件,而只是等待块进入,那么浏览器应该在块可用时立即开始写入块。但是如果没有丑陋的 setTimeout
循环,我无法弄清楚如何做到这一点;想不通怎么发个活动说不用等了,可以继续写了。
执行此操作的最佳模式是什么?
有一种方法可以在不超时的情况下做到这一点,虽然它使用标志来指示写入器可用,但它仍然比超时循环更好。
我会创建一个队列,当数据块到达时将存储在该队列中,并使用异步 fileWriter(当它完成写入文件时执行回调)。
像那样:
var readyToWrite = true;
var chunks = [];
var onData = function(data) {
chunks.push(data);
if (readyToWrite) {
writeChunksToFile(chunks);
}
};
var writeChunksToFile = function() {
if (chunks) {
readyToWrite = false;
fileWriter.write(chunks.shift(), function() {
writeChunksToFile(chunks);
});
} else {
readyToWrite = true;
}
};
这样 writer 一直写到 chunks 变空,然后它通知数据接收者(使用标志)它可用,所以数据接收器 (onData) 知道它必须在接收到下一个块时再次调用它。如果数据接收者获取数据并且 writer 仍在写入文件,那么它不会调用它,它只会将块推送到我们的队列数组,写入器将在完成时获取该块他的写作,因为它是递归调用的。
这是我们可以使用该方法编写的最简单的代码,但是您可以使用 ObserverPattern 或 "more functional" 使用 单子.