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

循环调用Firebase获取数据时数组更新后无法读取问题求助

解决Firebase异步调用循环中更新数组的问题

你遇到的问题核心就是Firebase的数据库请求是异步操作——JavaScript不会等待这些请求完成,就直接执行了后面的打印逻辑。这时候newArray还没被填充,所以看不到输出;之后你能看到数组元素,是因为异步请求完成后才把数据push进去,但已经错过了处理时机。

下面给你两种可行的解决方案,核心思路都是用Promise.all等待所有异步请求完成后,再处理数组:

方案1:使用async/await(更易读)

把函数改成异步函数,用await等待每个Firebase请求完成,再用Promise.all等待所有请求结束:

TestArrayUpdates = async () => {
  const namestoInsert = [ { name: 'Bob', score: 5 }, { name: 'Jim', score: 10 }, { name: 'steve', score: 15 } ];
  const newArray = [];

  // 把每个元素的异步请求包装成Promise,存入数组
  const updatePromises = namestoInsert.map(async (el) => {
    const idx = newArray.findIndex(item => item.name === el.name);
    if (idx === -1) {
      // 等待Firebase请求返回结果
      const snap = await firebase
        .database()
        .ref('userscoresbyday')
        .child('2019-Aug-30')
        .child('bgmd0r5HyZViLQZBynXUSm9e9Ab2')
        .once('value');
      
      let dayscore = 0;
      if (snap.exists()) {
        dayscore = snap.val().score;
      }
      const newscore = el.score + dayscore;
      newArray.push({ name: el.name, score: newscore });
    }
  });

  // 等待所有异步请求全部完成
  await Promise.all(updatePromises);

  // 现在newArray已经填充完毕,可以正常处理
  newArray.forEach((el) => {
    console.log(el.name);
  });
};

方案2:使用Promise.all + 回调(不依赖async/await)

如果你的环境不支持async/await,可以手动把每个请求包装成Promise:

TestArrayUpdates = () => {
  const namestoInsert = [ { name: 'Bob', score: 5 }, { name: 'Jim', score: 10 }, { name: 'steve', score: 15 } ];
  const newArray = [];

  const updatePromises = namestoInsert.map((el) => {
    return new Promise((resolve) => {
      const idx = newArray.findIndex(item => item.name === el.name);
      if (idx === -1) {
        firebase
          .database()
          .ref('userscoresbyday')
          .child('2019-Aug-30')
          .child('bgmd0r5HyZViLQZBynXUSm9e9Ab2')
          .once('value', snap => {
            let dayscore = 0;
            if (snap.exists()) {
              dayscore = snap.val().score;
            }
            const newscore = el.score + dayscore;
            newArray.push({ name: el.name, score: newscore });
            resolve(); // 标记当前Promise完成
          });
      } else {
        resolve(); // 元素已存在,直接标记完成
      }
    });
  });

  // 所有请求完成后处理数组
  Promise.all(updatePromises).then(() => {
    newArray.forEach((el) => {
      console.log(el.name);
    });
  });
};

关键注意点

  1. 一定要用const/let声明变量,避免全局变量污染(原代码里namestoInsert、newArray都没声明,容易引发意外问题)
  2. Promise.all会等待所有异步操作结束,这时候newArray才会被完全填充,后续的打印或处理逻辑才能拿到正确的数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:06:53