Web Streams 和 Node.js Stream API 之间的区别

bki*_*iac 16 javascript browser stream node.js typescript

我正在构建一个文件上传应用程序来熟悉流的概念。我正在尝试将文件列表或 blob 转换为流,然后将其上传到后端并将其存储在文件系统中。

我分别对前端和后端实现没有任何问题,但我很难将两者联系起来。我的主要问题是我不明白Web Streams APINode.js Streams API之间的区别。我设法将浏览器中选定输入文件的 blob 转换为 Web,ReadableStream但我尝试的包(axios对于请求socket.iosocket.io-streamWebSocket)只接受 Node.js 版本 Stream 作为参数。我也无法通过管道将 Web ReadableStream 导入 Node.js 可写流或双工流。方法名称也不同(例如:pipeTopipeThrough在 Web API 和pipeNode.js API 中)。

我知道 Node.js 和浏览器之间存在实现差异,但天真地,我认为 API 会相似。我能否以某种方式在 Web 流和浏览器化的 Node.js 流之间进行简单的转换,但我遗漏了什么?是否值得使用 Web Stream API stream-browserify

101*_*owz 7

手动将 Web 流转换为 Node.js 流并不太困难,但您确实应该尝试找到一个接受本机 Web 流的库,而不是使用streamBrowserify 将 Node.js 填充程序硬塞到浏览器中。

但是,如果证明有必要在浏览器中使用 Node.js 流 shim,则需要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;
}
Run Code Online (Sandbox Code Playgroud)

这些方法应该足以在 Web 和 Node 流之间实现完整的互操作。例如,如果要将 Web ReadableStream 通过管道传输到 Node.js Writable/Duplex:

const pipeWebRSToWritable = (rs, writable) => {
  // After converting you can use the normal pipe methods
  webRSToNodeRS(rs).pipe(writable);
}
Run Code Online (Sandbox Code Playgroud)

不过我想提一下,您不需要库来将数据从客户端流式传输到服务器。该fetchAPI 本身支持网络流,并且可能是您应该采用的方式。

// 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
});
Run Code Online (Sandbox Code Playgroud)

最后注意事项:确保您直接使用该Blob.prototype.stream方法(在对象上调用此方法File,例如file.stream(),因为Fileextends Blob)。有一些方法可以ReadableStream从 JS 中的文件中获取 a,实际上最终会将所有文件加载到浏览器的内存中,这是您不希望看到的。


leo*_*loy 7

根据文档,从版本 16 开始,Node.js 包含了WebStreams API 的(仍处于实验阶段)实现

旧的 Stream API 现在(自 v.17 起)获得了一些toWeb/FromWeb方法来桥接两者。

这里有一些信息。