2017-02-11 51 views
0

我發現方法的stream.Writable類不會順序寫入數據。當我以塊發送附件到服務器時,如果沒有延遲發生,此代碼按錯誤順序組裝數據塊。如果我在循環中間放置了一個類似console.log()的調試消息(如轉儲數據以實際監視正在寫入的內容),則此錯誤消失。那麼,這段代碼中的競爭條件是什麼?看起來我正在強制執行文件的順序組裝,所以我不明白什麼是錯的。write()不寫序列?

我的代碼:

function join_chunks(company_id,attachment_id,num_chunks) { 
    var stream; 
    var file; 
    var output_filename=ATTACHMENTS_PATH + '/comp' + company_id + '/' + attachment_id + '.data'; 
    var input_filename; 
    var chunk_data; 
    var chunk_count=0; 
    stream=fs.createWriteStream(output_filename,{flags:'w+',mode: 0666}); 
    console.log('joining files:'); 
    for(var i=0;i<num_chunks;i++) { 
     input_filename=ATTACHMENTS_PATH + '/comp' + company_id + '/' + attachment_id + '-' + (i+1) + '.chunk'; 
     console.log(input_filename); 
     fs.readFile(input_filename , (err, chunk_data) => { 
      if (err) throw err; 
      stream.write(chunk_data,function() { 
       chunk_count++; 
       if (chunk_count==num_chunks) { 
        console.log('join finished. closing stream'); 
        stream.end(); 
       } 
      }); 
     }); 
    } 
} 

控制檯:

joining files: 
/home/attachments/comp-2084830518/67-1.chunk 
/home/attachments/comp-2084830518/67-2.chunk 
/home/attachments/comp-2084830518/67-3.chunk 
/home/attachments/comp-2084830518/67-4.chunk 
join finished. closing stream 

節點版本:v6.9.2

+2

'fs.readFile'是異步的;您立即對'num_chunks'文件操作進行排隊,但它們不一定按照您排隊的順序完成。你可能需要等到他們全部完成,然後把它們整理好並寫下來。 – qxz

+0

@qxz,好眼睛。閱讀是問題,而不是寫作。我用順序流代替了閱讀,一切運行良好。如果你回答這個問題,我會接受它。另一個答案是錯誤的。 – Nulik

回答

1

stream.write是一個異步操作。這意味着多次調用它可能會失序服務。

如果您希望您的寫入按順序進行,請使用stream.writeSync,或使用stream.write的回調參數對您的寫入進行排序。

+0

謝謝。文檔中是否有某處說Writable.write()方法的執行順序不正確?或者你在哪裏讀過這些內容? – Nulik

+0

據我瞭解,爲了順序寫入而創建了'Writable'流,所以它應該在FIFO模式下默認保持順序。 – Nulik

+0

@Nulik一般來說,Node中的所有系統調用都是異步的,除非文檔另有明確說明。在回調之類的顯式同步點之外,不能保證異步調用的順序。 – duskwuff