javascript - Firebase 数据与 JavaScript 的异步 promise 相结合

标签 javascript firebase firebase-realtime-database promise

我声明了一个异步获取 Firebase 数据的函数。该函数必须等到所有数据都放入对象中。由于某种原因,该函数会继续执行,而不等待对象被设置。

/** Get the data content */
const getData = async (widget, userId) => {
  let promises = [];
  let mainObject = {};
  const pivotData = {};
  const pivotName =
    'user' + widget[1].type.charAt(0).toUpperCase() + widget[1].type.slice(1);

  //Object entries
  mainObject = {
    default: widget[1],
  };
  mainObject['widgetId'] = widget[0];

  //Main listner
  const mainRef = firebase
    .database()
    .ref()
    .child(widget[1].type);

  //Pivot Listner
  const pivotRef = firebase
    .database()
    .ref()
    .child(pivotName)
    .child(userId);

  //Set promise
  promises.push(
    new Promise(async resolve => {
      pivotRef
        .once('value', snapPivot => {
          snapPivot.forEach(function(result) {
            if (result.val().widgetId === widget[0]) {
              pivotData[result.key] = result.val();
              mainObject['pivot'] = pivotData;
              mainObject['typeId'] = result.key;
              mainObject['main'] = {};
              console.log('1');

              mainRef.child(result.key).once('value', snapshot => {
                console.log('2');
                mainObject['main'][result.key] = snapshot.val();
              });
            }
          });
        })
        .then(() => {
          resolve();
          console.log('3');
        });
    })
  );

  Promise.all(promises).then(results => {
    return mainObject;
  });
};

console.logs 的预期结果是 1,2,3,但它显示的是 1,1,3,2

Console image

为什么该函数不在循环内等待 .once 函数?

最佳答案

问题是您没有等待 mainRef.child(result.key).once() 的 promise 来解决。

此外,您只将一个 promise 推送到您的 promise 数组中,而您希望推送在调用 mainRef.child(result.key).once() 时获得的 promise 。

使用await Promise.all() see MDN .

// Reference.once returns a promise Promise<DataSnapshot>
const dataSnapshot = await pivotRef.once('value');

let promises = []; 
dataSnapshot.forEach((result) => {
  const key = result.key;
  const data = result.val();

  if (data.widgetId === widget[0]) {
    pivotData[key] = data;
    mainObject['pivot'] = pivotData;
    mainObject['typeId'] = key;
    mainObject['main'] = {};
    console.log('1');

    const promise = mainRef.child(result.key)
      .once('value', snapshot => {
        console.log('2');
        mainObject['main'][result.key] = snapshot.val();
      });        
    // add promise to our promises array
    promises.push(promise);
  }
});

// wait for all the promises to be fulfilled (i.e resolved)
await Promise.all(promises);

// assuming 3 only needs to be logged once (at the end)
console.log('3');
console.log(mainObject);
return mainObject;

让我知道这是否有效!

关于javascript - Firebase 数据与 JavaScript 的异步 promise 相结合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59214161/

相关文章:

java - 为什么即使在重写方法中发生更改,也会返回 null?

Firebase 您的 Cloud Firestore 数据库对于基本安全规则有不安全的规则

javascript - 从多个对象获取属性(如果存在)

javascript - 安卓浏览器 : programmatically change focused input value

firebase - Flutter Firebase Cloud Messaging onMessage 被触发两次

javascript - Firebase:如何将用户从 firebase.auth().onAuthStateChanged 异步绑定(bind)到 Angular 模板?

swift - 条件绑定(bind)的初始化程序必须具有可选类型,而不是 'String' ?

ios - Firebase AppCheck 的目的是什么?

javascript - jQuery datetimepicker - 如何在 JavaScript 中获取日期?

javascript - 使用 webpack 提取 Scss