从客户端订阅 NodeJS 服务器上的长处理请求反馈

Subscribe to long-processing request feedback on NodeJS server from client

我创建了一个执行以下操作的 Node JS 服务器:

  1. 使用 multer 将媒体文件(视频和图像)上传到服务器
  2. 如果媒体是图像,则使用清晰度调整大小
  3. 如果媒体是视频,则使用 fluent-ffmpeg 调整大小并压缩它
  4. 将文件上传到 Firebase 存储进行备份

这一切都在流利地工作。问题是,当上传的文件很大时,请求处理需要很长时间。所以我想在客户端显示一些进展如下:

Firebase 存储 API 在我们创建上传任务时具有如下所示的功能:

let uploadTask = imageRef.put(blob, { contentType: mime });
uploadTask.on('state_changed', (snapshot) => {
  if (typeof snapshot.bytesTransferred == "number") {
    let progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    console.log('Upload is ' + progress + '% done');
  }
});

我发现,可以使用 websockets 实现这一点,如果有其他方法可以做到这一点,我很感兴趣。

这里也描述了这个问题:http://www.tugberkugurlu.com/archive/long-running-asynchronous-operations-displaying-their-events-and-progress-on-clients

还有一种方法Accessing partial response using AJAX or WebSockets?,但我正在寻找更灵活、更专业的解决方案。

我已经使用 GraphQL 订阅解决了这个问题。使用 WebSockets 可以实现相同的方法。解决该问题的步骤如下:

  1. Post 文件上传服务器

  2. 生成操作唯一 ID 并将其作为响应发送给客户端

例如:response = {op: "A78HNDGS89NSNBDV7826HDJ"}

  1. 通过 opID 创建订阅

例如:subscription { uploadStatus(op: "A78HNDGS89NSNBDV7826HDJ") { status }}

  1. 每次状态更改时,都会向 GraphQL 端点发送请求,该端点将数据发布到 pubsub。要从 nodejs 服务器发送 GraphQL 请求,您可以使用 https://github.com/prisma-labs/graphql-request

例如:

const { request } = require('graphql-request');
const GQL_URL = "YOUR_GQL_ENDPOINT";
const query = `query {
    notify ("Status text goes here")
}`

request(GQL_URL, query).then(data =>
  console.log(data)
)

通知解析器函数将数据发布到 pubsub

 context.pubsub.publish('uploadStatus', {
     status: "Status text"
 });

如果你有更复杂的架构,你可以使用 RabbitMQ、Kafka 等消息代理

如果有人知道其他解决方案,请告诉我们)