Firebase数据与javascript的异步承诺相结合

时间:2019-12-06 13:31:26

标签: 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函数?

1 个答案:

答案 0 :(得分:0)

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

另外,您只将一个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;

让我知道这是否有效!