我试图通过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
循环,我无法弄清楚如何做到这一点;我无法弄清楚如何发布一个说我们不再需要等待的事件,并且可以继续写作。
这样做的好方法是什么?
答案 0 :(得分:1)
有一种方法可以在没有超时的情况下做到这一点,虽然它使用标志来指示编写器可用,它仍然应该比超时循环更好。
我会创建队列,当数据块到达时将存储数据块并使用async 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 正在编写,直到 chunk 变为空,然后它通知数据接收者(使用flag)它是否可用,所以数据接收器( onData < / em>)知道它必须在收到下一个块时再次调用它。如果数据接收器获取数据并且 writer 仍在写入文件,那么它将不会调用它,它只会将chunk推送到我们的队列数组,而编写器将在完成写入时获得该块,因为它是递归调用的。
这是我们用这种方法编写的最简单的代码,但您可以使用 Monserver 使用 ObserverPattern 或“更多功能”使其“更多OOP”。