I'm trying to make React's renderToString
and renderToStaticMarkup
a better citizen by yielding to the event loop allowing other server requests to get a look in, e.g.
const React = require('react');
const { renderToNodeStream } = require('react-dom/server');
// Wrap `renderToNodeStream` in promise
const renderToStringAsync = node => {
return new Promise((resolve, reject) => {
let body = '';
const stream = renderToNodeStream(node);
// NOTE: we're turning the tap on full blast here, but I still expected it to yield
stream.on('data', chunk => {
console.log('Received chunk');
body += chunk.toString();
});
stream.on('error', ex => {
reject(ex);
});
stream.on('end', () => {
resolve(body);
});
});
};
setTimeout(() => {
console.log('Yielded to event loop');
}, 0)
await renderToStringAsync(largeRootNode);
I expected this:
// Expect:
// Received chunk
// Yielded to event loop
// Received chunk
// Received chunk
// Received chunk
// Received chunk
// Received chunk
// Received chunk
// Received chunk
// Received chunk
// Received chunk
But I actually get this:
// Actual:
// Received chunk
// Received chunk
// Received chunk
// Received chunk
// Received chunk
// Received chunk
// Received chunk
// Received chunk
// Received chunk
// Yielded to event loop
I'm wondering if it's related to .on('data')
; I know it doesn't manage backpressure, but I had always thought it would be async?
NOTE: I'm not piping the response to the client as I need to wait for the render to complete before determining the status code; I merely want to use
renderToNodeStream
to improve cooperative multitasking in node.js)