Запрашивая https://httpbin.org/stream/3
, сервер отправляет данные, разделенные на 3 части, через поток. Клиент (в данном случае скрипт вашего узла) поддерживает связь с сервером, продолжает получать данные и разбивает их на части.
node-fetch
просто разбивает данные на фрагменты каждый раз, когда выполняется одна асинхронная задача, как вы можете видеть здесь: строка 199 body.js.
Поэтому, если разделенные данные поступают так быстро, что асинхронная задача получает несколько блоков данных в цикле событий одного узла, node-fetch
получает несколько данных Джейсона.
Вот тогда и возникает ошибка. Запустите следующий код с добавлением console.log
. Затем вы можете подтвердить, что при возникновении ошибки несколько объектов jason сохраняются в chunk
.
.
const fetch = require('node-fetch');
async function main () {
const response = await fetch('https://httpbin.org/stream/3');
try {
for await (const chunk of response.body) {
console.log("------chunk-----\n", chunk.toString());
console.log("Char at 310 -- 315", chunk.toString().substring(310, 315));
console.log(JSON.parse(chunk.toString()));
}
} catch (err) {
console.error(err.stack);
}
}
main()
Для этого сайта вы можете разделить данные самостоятельно, когда возникает следующая ошибка.
const fetch = require('node-fetch');
async function main () {
const response = await fetch('https://httpbin.org/stream/3');
try {
for await (const chunk of response.body) {
try {
console.log(JSON.parse(chunk.toString()));
} catch (_) {
console.log("------ Handling multiple chunks ------");
chunk.toString().split("\n").slice(0, -1).forEach(d => console.log(JSON.parse(d)));
}
}
} catch (err) {
console.error(err.stack);
}
}
main()
При использовании Fetch API с браузером вы можете написать свой собственный ReadableStreamReader и реализовать стратегию обработки разделенных данных.
Обновление:
Вы можете просто использовать библиотеку stream-json
jsonl Parser следующим образом:
const { parser: jsonlParser } = require('stream-json/jsonl/Parser');
async function main () {
const response = await fetch('https://httpbin.org/stream/5');
response.body.pipe(jsonlParser())
.on('data', ({ key, value }) => console.log(value))
.on('end', () => console.log("Parsing done."))
.on('error', err => console.log(err.message));
}
main();