我正在尝试从 NodeJS 服务器流式传输大量数据,该服务器从 Mongo 获取数据并将其发送到 React。由于它是相当多的数据,我决定从服务器流式传输它,并在它进入后立即在 React 中显示它。这是我在服务器上得到的内容的稍微简化的版本:
const getQuery = async (req, res) => {
const { body } = req;
const query = mongoQueries.buildFindQuery(body);
res.set({ 'Content-Type': 'application/octet-stream' });
Log.find(query).cursor()
.on('data', (doc) => {
console.log(doc);
const data = JSON.stringify(result);
res.write(`${data}rn`);
}
})
.on('end', () => {
console.log('Data retrieved.');
res.end();
});
};
这是 React 部分:
fetch(url, { // this fetch fires the getQuery function on the backend
method: "POST",
body: JSON.stringify(object),
headers: {
"Content-Type": "application/json",
}
})
.then(response => {
const reader = response.body.getReader();
const decoder = new TextDecoder();
const pump = () =>
reader.read().then(({ done, value }) => {
if (done) return this.postEndHandler();
console.log(value.length); // !!!
const decoded = decoder.decode(value);
this.display(decoded);
return pump();
});
return pump();
})
.catch(err => {
console.error(err);
toast.error(err.message);
});
}
display(chunk) {
const { data } = this.state;
try {
const parsedChunk = chunk.split('rn').slice(0, -1);
parsedChunk.forEach(e => data.push(JSON.parse(e)));
return this.setState({data});
} catch (err) {
throw err;
}
}
无论它是没有问题地完成还是在 React 方面失败,都是 50/50。当它失败时,总是因为parsedChunk.forEach中的JSON对象不完整。我做了一些挖掘,结果发现每次失败时,我用 3 个感叹号标记.log控制台显示 65536。我 100% 确定它与我的流实现有关,我没有正确排队块,但我不确定我是否应该在客户端或服务器端修复它。任何帮助将不胜感激。
与其像您在这里所做的那样实现自己的类似 NDJSON 的流式 JSON 协议(将流划分为并不总是在您的控制下的块和数据包的所有陷阱),您可以查看一些为完成您需要的事情而创建的现有工具,例如:
- http://oboejs.com/
- http://ndjson.org/
- https://www.npmjs.com/package/stream-json
- https://www.npmjs.com/package/JSONStream
- https://www.npmjs.com/package/clarinet