[英]Node.js writable.write return false?
我想上傳(流)控制寫入過程。 但寫作過程總是返回false。 大文件上傳過程停止。 代碼的輸出如下;
> Node app.js
> False
> False
> False
> False
我究竟做錯了什么?
我的代碼;
app.js
var http = require('http');
var fs = require('fs');
http.createServer(function(req, res){
var readable = fs.createReadStream('read.mkv');
var writable = fs.createWriteStream('write.mkv');
readable.on('data', function(chunk){
var buffer = writable.write(chunk);
if(!buffer){ // ----> Always false! Why????
readable.pause();
}
console.log(buffer);
});
writable.on('drain', function(){
readable.resume();
});
}).listen(8090);
我修改了您的程序以顯示有關正在發生的事情的更多信息:
'use strict';
const fs = require('fs');
const readable = fs.createReadStream('read.mkv');
const writable = fs.createWriteStream('write.mkv');
readable.on('data', function(chunk){
var buffer = writable.write(chunk);
if(!buffer){ // ----> Always false! Why????
readable.pause();
}
console.log(buffer, chunk.length);
});
writable.on('drain', function(){
readable.resume();
console.log('drain');
});
輸出:
$ node blah.js
false 65536
drain
false 65536
drain
false 65536
drain
true 8192
我還使用了不同大小的文件作為輸入,所以我在輸出的末尾有一個true
。 如果我將read.mkv
的大小增加了例如10000
字節,則最后一行將讀取為false 18192
。
發生的事情是read()
返回的每個塊都足夠大,導致寫入流超過其highWaterMark
,默認為16384
(假設fs.createWriteStream
返回的流)。 從輸出中的數字可以看出,每個read()
(錯誤,每個'data'
事件)產生65536
個字節,除了最后一個。 由於將此數據量writable
會導致其超過其highWaterMark
,因此該流建議在繼續之前等待'drain'
。
因此,簡單地說,您總是看到false
發射,因為readable
流在讀取時會產生如此大的塊。 我希望不再看到任何日志表明轉移已經完成。 但是你真的需要注冊.on('end')
和.on('error')
來解決這個問題。
對於像這樣的簡單情況,最好只使用readable.pipe()
,如:
readable.pipe(writable);
這將自動處理'drain'
。 它甚至會適當地為你調用writable.end()
。
請注意,如果遇到讀取或寫入錯誤, pipe()
將不會調用writable.end()
。 如果您有一個需要對流錯誤具有彈性的長時間運行進程,則需要確保處理錯誤並關閉流以防止在程序運行足夠長時間以達到文件描述符限制時出現句柄泄漏。
false
意味着什么 Streams允許程序通過一次處理一個塊而不是將其全部加載到內存中來擴展到大量數據。 在最終寫出數據之前,可以將流組織成表示數據上的各種變換的流水線。 當write()
返回false
,它表示已收到足夠的數據以使其保持一段時間。 如果你不斷發送它,它將繼續接受這些塊。 但是,其積壓的數據將增長並開始消耗更多內存。 如果忽略此返回值並繼續從非常大的源發送數據,您甚至可能導致程序耗盡其地址空間並崩潰或卡住。 為了保持代碼的可擴展性,您應該尊重false
返回並等待代碼中的'drain
'。
但是, false
並不意味着發生了任何錯誤或存在任何錯誤。 實際上,在源流比目標流快的任何情況下,預計會發生這種情況,並且是流API保持安全的方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.