nga*_*n93 5 javascript json stream
我正在获取一个大的 JSON 文件(200mb),并且我想将这些数据呈现为数据流中的数据。我遇到的问题是,在解码和解析流式传输给我的块后,会返回一个语法错误我Unexpected end of JSON input在控制台中。我想要做的是解析返回块并在获得数据后立即对其进行处理。但是,由于 ReadableStream 以块的形式进行流式传输,而这些块的切片方式是不可预测的,因此我无法对返回值执行 JSON.parse() 。需要进行什么样的数据处理才能实现这一点?有更好的方法吗?
这是我的代码:
const decoder = new TextDecoder('utf-8')
fetch("../files/response.json")
.then(response => {
const reader = response.body.getReader()
new ReadableStream({
start(controller) {
function enqueueValues() {
reader.read()
.then(({ done, value }) => {
if (done) {
controller.close() // stream is complete
return
}
var decodedValue = decoder.decode(value) // one chunk of invalid json data in string format
console.log(JSON.parse(decodedValue)) // json syntax error
// do something with the json value here
controller.enqueue(value)
enqueueValues() // run until all data has been streamed
})
}
enqueueValues()
}
})
})
Run Code Online (Sandbox Code Playgroud)
我认为实现这一点的唯一方法是在每个块中发送有效的 json 数据(对象、数组)。
这是一个示例express.js处理程序:
app.get("/stream", (req, res) => {
let i = 0;
const interval = setInterval((a) => {
i += 1;
res.write(JSON.stringify([{ message: `Chunk ${i}` }]));
}, 500);
setTimeout(() => {
clearInterval(interval);
res.end(() => {
console.log("End");
});
}, 5000);
});
Run Code Online (Sandbox Code Playgroud)
这样做的缺点是最终的 json(所有块连接成一个字符串)无效。但是在浏览器内存中保存 200mb 的对象也不好。
更新:我试图解决我的项目中的类似问题并找到了解决方法。
然后在客户端上,我忽略等于[and的块],并剪切每个数据块中的结尾逗号。
服务器:
app.get("/stream", (req, res) => {
let i = 0,
chunkString;
res.write("["); // <<---- OPENING bracket
const interval = setInterval((a) => {
i += 1;
chunkString = JSON.stringify({ message: `Chunk ${i}` });
res.write(`${chunkString},`); // <<----- Note ending comma at the end of each data chunk
}, 500);
setTimeout(() => {
clearInterval(interval);
res.end("]", () => {. // <<---- CLOSING bracket
console.log("End");
});
}, 5000);
});
Run Code Online (Sandbox Code Playgroud)
客户:
const decoder = new TextDecoder("utf-8");
const handleJsonChunk = (jsonChunk) => {
console.log("Received Json Chunk: ", jsonChunk);
};
const main = async () => {
const response = await fetch("http://localhost:3000/stream");
const reader = response.body.getReader();
const skipValues = ["[", "]"];
const work = (reader) => {
reader.read().then(({ done, value }) => {
if (!done) {
let stringValue = decoder.decode(value);
const skip = skipValues.indexOf(stringValue) >= 0;
if (skip) return work(reader);
if (stringValue.endsWith(","))
stringValue = stringValue.substr(0, stringValue.length - 1);
try {
const jsonValue = JSON.parse(stringValue);
handleJsonChunk(jsonValue);
} catch (error) {
console.log(`Failed to parse chunk. Error: ${error}`);
}
work(reader);
}
});
};
work(reader);
};
main();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1888 次 |
| 最近记录: |