首页 > 解决方案 > 使用 pipe() 时超过并发 React 渲染器的最大数量

问题描述

我有一个在 Kubernetes 中运行的带有 SSR 的 React 应用程序。几天没有重新启动 Pod 后,我收到此错误:https ://reactjs.org/docs/error-decoder.html/?invariant=304 。

我使用ReactDOMServer.renderToNodeStreamandpipe()并根据错误:

如果你没有正确销毁 React 提供的 Readable,就会发生这种情况。如果您不再想从中读取,请确保在其上调用 .destroy() 并且没有读到最后。如果你使用 .pipe() 这应该是自动的。

这是我的服务器渲染器:

export function renderOnServer(res, controller) {
    return new Promise((resolve, reject) => {
        try {
            const index = controller.getIndexHTML();
            const view = controller.getView();

            const indexHTML = `<!DOCTYPE html>${ReactDOMServer.renderToStaticMarkup(index)}`;
            const chunks = indexHTML.split("{{STREAMED_CONTENT}}");
            
            const firstChunk = chunks.shift();
            const lastChunk = chunks.shift();

            res.write(firstChunk);

            const stream = ReactDOMServer.renderToNodeStream(view);
            stream.pipe(res, { end : false });
            stream.on("end", () => {
                res.write(lastChunk);
                res.end();
                resolve();
            });
        } catch(err) {
            reject(err);
        }
    });
}

我使用pipe()但我也处理end代码中看到的事件。这可能是问题的原因吗?还是我应该专注于代码的另一部分?

任何帮助表示赞赏。谢谢。

标签: reactjsserver-side-renderingrenderer

解决方案


你的代码似乎完全没问题。也许这是一些奇怪的 React 库的问题。您可以执行以下操作:

  1. 将 ReactJS 库和 NodeJS 更新到当前版本
  2. 尝试在“结束”回调函数中销毁流:
stream.on("end", () => {
   stream.destroy(); // but I think it is not necessary
   res.write(lastChunk);
   res.end();
   resolve();
});
  1. 你应该添加stream.on("error", () => something to do)回调函数

或者您可以用 renderToString 替换 renderToNodeStream 调用。它不如使用流的内存效率高,但在您的情况下更安全。


推荐阅读