【问题标题】:Difference between Web Streams and Node.js Stream APIsWeb Streams 和 Node.js Stream API 之间的区别
【发布时间】:2020-07-28 15:11:32
【问题描述】:

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

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

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

【问题讨论】:

  • 这需要一些示例代码。我不知道 OP 的困惑在于前端还是后端。您不能在 browserland 中使用 Node 流,因此我假设没有需要 Node 流的 browserland 库。在后端,您只处理节点流:即使使用浏览器流向服务器流式传输的数据也会在服务器端呈现为节点流。如果没有一些代码,很难想象在所有的创作中 OP 的问题甚至可能存在。

标签: javascript node.js typescript browser stream


【解决方案1】:

手动将 Web 流转换为 Node.js 流并不难,但您应该真正尝试找到一个接受本机 Web 流的库,而不是为 stream 内置使用 Browserify 进入浏览器。

但是,如果证明有必要在浏览器中使用 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;
}

这些方法应该足以在 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);
}

但是我想提一下,您不需要库来将数据从客户端流式传输到服务器。 fetch API 原生支持网络流,可能是您应该采用的方式。

// 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 method(在File 对象上调用它,例如file.stream(),因为File 扩展了Blob)。有一些方法可以从 JS 中的文件中获取ReadableStream,实际上最终会将所有文件加载到浏览器的内存中,这是您不想要的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-06
    • 2016-11-29
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 2017-10-02
    • 2013-09-24
    相关资源
    最近更新 更多