用于将块写入文件的事件驱动模式 - JS

时间:2015-05-27 07:03:40

标签: javascript design-patterns file-io webrtc event-driven-design

我试图通过WebRTC传输文件,而且我正在努力找出一个好的模式来编写数据,因为它正在进入。由于文件块将会进入未知的速率,我需要能够在每个块可用时编写它们;这意味着两件事:

  1. 如果数据进入太快,那么我们需要在当前写入任务完成后对每个块进行排队以便稍后写入
  2. 如果数据进展太慢,那么我们需要等待一个块可用
  3. 理想情况下,我希望避免依赖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循环,我无法弄清楚如何做到这一点;我无法弄清楚如何发布一个说我们不再需要等待的事件,并且可以继续写作。

    这样做的好方法是什么?

1 个答案:

答案 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”。