承诺不等待异步对象条目Firebase调用

时间:2019-12-06 11:57:25

标签: javascript firebase asynchronous promise

我有一个主要功能,可以等待并并行连接几个功能,如下所示:

主要功能:

console.log('A');
const pivotData = await Promise.all(
    Object.entries(thenWidgets.val()).map(widget => {
      getPivot(widget, userId)
      console.log('B');
    });
);
console.log('C');
console.log('D');
const mainData = await Promise.all(
    pivotData.map(widget => getMain(widget))
);
console.log('F');
mainData.map(item => {
    return (finalObject[item.widgetId] = item);
});
console.log('G');

在到达console.log('D')以下的mainData之前,该工作正常。似乎不等待诺言就跳到console.log('F')而不等待拥有console.log('E')的getMain函数

getMain()函数:

const getMain = widget => {
  return new Promise(resolve => {
    var requests = [];
      const pivotData = {};
        Object.keys(widget.pivot).map(item => {
          const mainRef = firebase
            .database()
            .ref()
            .child(widget['default'].type)
            .child(item);

          mainRef.once('value', snapMain => {
            pivotData[item] = snapMain.val();
          }).then(() => {
            widget['main'] = pivotData;
            console.log('E');
            requests.push('test');
          });
          console.log('E2')
        })
        Promise.all(requests)
        .then(() => {
          console.log('E3');
          resolve(widget);
        })
        .catch(error => console.log(`Error in promises ${error}`));
  });
};

这里的预期结果是:“ E,E2,E,E2,E3”,但是我得到的是“ E2,E2,E3”,然后它返回了承诺。后来,在所有诺言解决之后,我得到了“ E,E”。所以整个事情的预期结果应该是“ A,B,C,D,E,E2,E,E2,E3,F,G”,我现在是“ A,B,C,D,E2,E2 ,E3,F,G,E,E'

似乎Object.keysgetMain()内部的诺言没有等待mainRef.once。也许我缺少了一些东西。

我的问题是:诺言没有等待getMain()函数,这出了什么问题?

1 个答案:

答案 0 :(得分:1)

让我们仔细看一下getMain函数,特别是console.log('E')周围的行。以下是发生的情况:

  1. 在这里您拨打Firebase的电话,.once(...)返回的不是await的承诺,因此稍后{em {em}之后 {em}返回
  2. 由于未对getMain进行承诺,因此要执行的下一行是await,然后在循环的下一次迭代中进行
  3. 循环完成后,console.log('E2')将是一个空数组(因为期望值来自requests处理程序,但我们从未等待过这些诺言)。空数组立即得到解析,因此.once(...)进入Promise.all(requests)部分,注销“ E3”并解析主要承诺,有效地返回了原始小部件
  4. 一旦then返回,我们先前创建的Promise将开始解析和修改“幕后”窗口小部件,因此下次您尝试对窗口小部件执行任何操作时,您可能会发现完全出乎意料的事情。 / li>

要修复此功能,您需要先等待Firebase返回的承诺,然后再进入底部的主要承诺-您可以通过将{{1 }}调用一个新数组,并在该数组上getMain,或者通过在每次循环迭代中编写一个“链式” promise,然后在循环之后立即等待它

希望有帮助!