繁体   English   中英

stream JSON 从 REST ZDB974238714CA38DE634A7CE1D 到 Express 应用程序的最佳方法是什么?

[英]What is the best approach to stream JSON from a REST API to an Express app?

我有一个基于分子的微服务,它的端点输出一个大的 JSON object (大约数万个对象)

这是一个结构化的 JSON object,我事先知道它会是什么样子。

[ // ... tens of thousands of these
  {
    "fileSize": 1155624,
    "name": "Gyo v1-001.jpg",
    "path": "./userdata/expanded/Gyo v01 (2003)"
  },
  {
    "fileSize": 308145,
    "name": "Gyo v1-002.jpg",
    "path": "./userdata/expanded/Gyo v01 (2003) (Digital)"
  }
  // ... tens of thousands of these
]

我开始研究 JSON 流,并在那里取得了一些进展,因为我知道如何使用 NodeJS ReadableStream客户端。 我知道我可以使用oboe来解析 JSON stream。

为此,这是我基于 Express 的应用程序中的代码。


router.route("/getComicCovers").post(async (req: Request, res: Response) => {
  typeof req.body.extractionOptions === "object"
    ? req.body.extractionOptions
    : {};
  oboe({
    url: "http://localhost:3000/api/import/getComicCovers",
    method: "POST",
    body: {
      extractionOptions: req.body.extractionOptions,
      walkedFolders: req.body.walkedFolders,
    },
  }).on("node", ".*", (data) => {
    console.log(data);
    res.write(JSON.stringify(data));
  });
});

这是moleculer中的端点

getComicCovers: {
    rest: "POST /getComicCovers",
    params: {
        extractionOptions: "object",
        walkedFolders: "array",
    },
    async handler(
        ctx: Context < {
            extractionOptions: IExtractionOptions;
            walkedFolders: IFolderData[];
        } >
    ) {
        
        const comicBooksForImport = await getCovers(
            ctx.params.extractionOptions,
            ctx.params.walkedFolders
        );

// comicBooksForImport is the aforementioned array of objects.
// How do I stream it from here to the Express app object-by-object?

        
    },
},

我的问题是:我如何 stream 这个巨大的 JSON 从 REST 端点到 Express 应用程序,以便我可以在客户端解析它?

更新

根据@JuanCaicedo 的建议,我使用了socket.io实现。 我在服务器端和客户端都设置了它。

但是,我确实对这段代码有疑问

map(
    walkedFolders,
    async (folder, idx) => {
        let foo = await extractArchive(
            extractionOptions,
            folder
        );

        let fo =
            new JsonStreamStringify({
                foo,
            });

        fo.pipe(res);
        if (
            +idx ===
            walkedFolders.length - 1
        ) {
            res.end();
        }
    }
);

我收到Error [ERR_STREAM_WRITE_AFTER_END]: write after end错误。 我知道发生这种情况是因为响应在下一次迭代尝试 pipe 更新值foo (这是一个流)到响应之前终止。

我该如何解决这个问题?

您是在寻求一般方法建议,还是寻求对您拥有的特定解决方案的支持?

如果是第一个,那么我认为在服务器和客户端之间进行通信的最佳选择是通过 websockets,也许使用Socket.io 之类的东西。 长寿命的连接将在这里为您提供很好的服务,因为传输所有数据需要很长时间。

然后,您可以随时将数据从服务器发送到客户端。 此时,您可以将服务器上的数据读取为 node.js stream 并一次发出一个数据。

使用 Oboe 并在每个节点上写入响应的问题在于它需要长时间运行的响应,并且在您发送所有数据之前连接很可能会中断。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM