[英]Difference between Web Streams and Node.js Stream APIs
我正在構建一個文件上傳應用程序來熟悉流的概念。 我正在嘗試將文件列表或 blob 轉換為流,然后將其上傳到后端並將其存儲在文件系統中。
我分別對前端和后端實現沒有問題,但我很難將兩者聯系起來。 我的主要問題是我不明白Web Streams API和Node.js Streams API之間的區別。 我設法將瀏覽器中選定輸入文件的 blob 轉換為 Web ReadableStream
,但我嘗試的包(請求的axios
,WebSocket 的socket.io
和socket.io-stream
)只接受 Node.js 版本的 Stream 作為參數。 我也無法將 Web ReadableStream 通過管道傳輸到 Node.js Writeable 或 Duplex Stream。 方法名稱也不同(例如:Web API 中的pipeTo
或pipeThrough
和 Node.js API 中的pipe
)。
我知道 Node.js 和瀏覽器之間存在實現差異,但我天真地認為 API 應該是相似的。 我能否以某種方式在 Web 流和瀏覽器化的 Node.js 流之間進行簡單的轉換,而我遺漏了什么? 在stream-browserify
上使用 Web Stream API 是否值得?
根據文檔,自版本 16 起,Node.js 包含WebStreams API 的(仍處於試驗階段)實現。
舊的 Stream API 現在(自 v.17 起)獲得了一些toWeb/FromWeb方法來橋接兩者。
這里有一些信息。
It's not too difficult to convert a web stream to a Node.js stream manually, but you should really try to find a library that accepts native web streams instead of shoehorning a Node.js shim for the stream
built-in into the browser with Browserify.
但是,如果證明有必要在瀏覽器中使用 Node.js stream 墊片,則需要安裝stream-browserify
並像這樣使用:
import { Readable, Writable } from 'stream-browserify;'
// window.ReadableStream to Node.js Readable
const webRSToNodeRS = rs => {
const reader = rs.getReader();
const out = new Readable();
reader.read().then(async ({ value, done }) => {
while (!done) {
out.push(value);
({ done, value }) = await reader.read();
}
out.push(null);
});
return out;
}
// window.WritableStream to Node.js Writable
const webWSToNodeWS = ws => {
const writer = ws.getWriter();
const out = new Writable();
out._write = (chunk, encoding, callback) => {
writer.write(chunk);
callback();
};
out._final = callback => {
writer.close();
callback();
};
return out;
}
這些方法應該足以在 web 和節點流之間進行完全互操作。 例如,如果您想將 pipe 和 web ReadableStream 轉換為 Node.js Writable/Duplex:
const pipeWebRSToWritable = (rs, writable) => {
// After converting you can use the normal pipe methods
webRSToNodeRS(rs).pipe(writable);
}
但是我想提一下,您不需要從客戶端到服務器的 stream 數據的庫。 fetch
API 原生支持 web 流,並且可能是您應該使用 go 的方式。
// POST a ReadableStream (perhaps of a file) to the server
// Way easier and more performant than using a 3rd party library...
const postRSToServer = rs => fetch('/your/server/endpoint', {
method: 'POST',
body: rs
});
最后一點:確保您直接使用Blob.prototype.stream
方法(在File
object 上調用此方法,例如file.stream()
,因為File
擴展了Blob
)。 有一些方法可以從 JS 中的文件中獲取ReadableStream
,實際上最終會將所有文件加載到瀏覽器中的 memory 中,這是您不想要的。
對於那些就node-fetch
返回的流提出這個問題的人(比如我自己),請注意undici是fetch
的web 兼容實現, 最終可能成為官方節點實現。
另外,請參閱leonbloy 的回答RE 新的 toWeb/fromWeb 方法和 WebStreams API。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.