浏览器端JavaScript如何实现大JSON Blob/Stream/Buffer的只读向前解析?
解决方案
问题根因
Oboe.js 内部默认会缓存所有已解析的JSON结构,同时你代码中把所有解析出的对象都存入
blocks数组,两者叠加会快速消耗浏览器内存,当加载到25万条数据时达到浏览器内存上限,就会抛出内存溢出错误。
推荐实现方案
用专门针对浏览器流式场景设计的@streamparser/json库,它完全实现了向前只读的JSON解析能力,和.NET的Utf8JsonReader逻辑一致,不会缓存任何已处理的历史数据,最低内存占用可控制在MB级别。
实现代码
可通过npm安装依赖:npm install @streamparser/json,也可直接引入对应的CDN资源使用。
import { parser } from '@streamparser/json' async loadAsync(file: Blob) { const blocks: any[] = this.blocks = [] const ms = Date.now() let counter = 0 // 直接读取Blob的字节流,不需要加载整个文件到内存 const stream = file.stream() .pipeThrough(parser({ // 匹配顶层数组的每一个元素,对应你的JSON结构:[obj1, obj2, ...] paths: ['$.*'] })) // 逐元素遍历解析结果 for await (const { value } of stream) { blocks.push(value) counter++ if (counter % 5000 === 0) { this.logFn(`Loading: ${counter} items so far.`) // 可选:这里可以加await new Promise(r => setTimeout(r, 0))让出主线程,避免页面卡死 } } this.logFn(`Finished loading ${counter} blocks in ${Date.now() - ms}ms`) }
优化建议
- 如果业务不需要保留所有已解析的对象,可以处理完单个
value后直接丢弃,不存入blocks数组,内存占用会极低,哪怕几GB的JSON文件也能正常处理 - 如果必须留存全量数据,建议每解析1~5万条就批量写入浏览器
IndexedDB持久化,不要全量存在内存中
内容的提问来源于stack exchange,提问作者Luke Vo
相关产品推荐
相关产品推荐

