You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript多JSON文件对比:全局变量无法访问问题求助

解决FileReader异步读取多JSON文件后无法正确访问全局数据的问题

兄弟,你完全戳中了JavaScript异步操作的痛点!你猜的没错,问题根源就是异步时序不对,再加上浏览器控制台的一个小特性,才让你出现“控制台能显示对象但展开不了、代码里访问属性是undefined”的诡异情况。

为啥会这样?

首先,FileReader的readAsBinaryString和onload是异步执行的——也就是说,当你调用readFile(0)之后,代码不会傻等着文件读完才往下走,而是立刻执行后面的console.log(data)和return data,这时候data还是个空对象,半毛钱数据都没塞进去。

至于Firefox控制台能显示对象但点不开的情况,是浏览器的惰性渲染机制在搞鬼:它打印的是data对象的引用,你刚打印的时候它确实是空的,但等你点击展开时,异步的文件读取已经完成,data已经被填充了数据,所以能看到内容,但代码里直接访问属性的时机早了一步,自然拿不到值。

另外还有个小问题:你复用了同一个FileReader实例读取多个文件,虽然当前代码逻辑是等前一个读完再读下一个,但这种写法有潜在冲突风险,最好每个文件用单独的reader实例。

怎么解决?

这里给你两种实用的修改方案,看你习惯哪种:

方案一:用Promise+async/await重构(推荐,代码更清晰)

把单文件读取包装成Promise,用异步语法确保所有文件读完后再处理数据:

var data = {};

// 把单个文件读取包装成Promise
function readSingleFile(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      try {
        const bin = JSON.parse(e.target.result);
        resolve(bin);
      } catch (err) {
        reject(err);
      }
    };
    reader.onerror = reject;
    reader.readAsBinaryString(file);
  });
}

async function readmultifiles(files) {
  // 依次读取每个文件(如果想并行读取可以用Promise.all,看你的需求)
  for (const file of files) {
    const bin = await readSingleFile(file);
    for (const task in bin['values']) {
      addData(bin['info']['date'], task, bin['values'][task]);
    }
  }
  console.log("所有文件读取完成");
  console.log(data);
  return data;
}

function addData(date, task, value) {
  if (!data[task]) {
    data[task] = {};
  }
  data[task][date] = value;
}

const fileInput = document.querySelector('#file');
fileInput.addEventListener('change', async function() {
  console.log(fileInput);
  const files = fileInput.files;
  // 等待所有文件读取完成再处理数据
  await readmultifiles(files);
  console.log("index");
  console.log(data);
  console.log(data['task_1']); // 现在就能正常访问啦
});

方案二:用回调函数(适合不支持async/await的旧环境)

如果不想用现代异步语法,也可以用回调函数来通知数据加载完成:

var data = {};

function readmultifiles(files, callback) { 
  let index = 0;
  function readFile() { 
    if( index >= files.length ) {
      console.log("所有文件读取完成");
      console.log(data);
      callback(data); // 全部读完后调用回调,把数据传出去
      return; 
    } 
    const file = files[index]; 
    // 每个文件用单独的FileReader实例,避免复用冲突
    const reader = new FileReader();
    reader.onload = function(e) { 
      const bin = JSON.parse(e.target.result); 
      for(const task in bin['values']){ 
        addData(bin['info']['date'], task, bin['values'][task]); 
      } 
      index++;
      readFile(); 
    } 
    reader.readAsBinaryString(file); 
  } 
  readFile(); 
} 

function addData(date, task, value){ 
  if(!data[task]){ 
    data[task] = {}; 
  } 
  data[task][date] = value; 
} 

const fileInput = document.querySelector('#file'); 
fileInput.addEventListener('change', function() { 
  console.log(fileInput); 
  const files = fileInput.files; 
  // 传入回调函数,等数据加载完再处理
  readmultifiles(files, function(loadedData) {
    console.log("index"); 
    console.log(loadedData); 
    console.log(loadedData['task_1']); // 这里就能拿到正确的值了
  });
});

内容的提问来源于stack exchange,提问作者Dams

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 13:07:53