【问题标题】:Promise not waiting in async Object entries firebase call承诺不在异步对象条目firebase调用中等待
【发布时间】:2020-03-31 10:06:54
【问题描述】:

我有一个 main 函数,它像这样等待并并行连接几个函数:

主要功能:

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'

似乎getMain() 中的Object.keys 中的promise 并没有等待mainRef.once。也许我错过了一些东西。

我的问题是:promise 不等待getMain() 函数出了什么问题?

【问题讨论】:

  • 请更新您的代码,因为存在语法错误并且很难判断出什么问题
  • 语法错误在哪里?
  • main函数的第三行,没有大括号,我不知道你是想添加大括号还是在仍然包含console.log时以某种方式返回getPivot,你的地图回调将返回@987654330 @
  • @KrzysztofKrzeszewski 我加了大括号
  • 好吧,看来你已经添加了大括号,但是 map 回调没有返回值(返回未定义),所以它会立即解决,在你的 promise.all 语句中没有值,对现在,无论您的 pivotData 是什么,都将是一个空数组(或者更确切地说是长度为 Object.entries(thenWidgets.val()).length 的数组,其中充满了未定义)

标签: javascript firebase asynchronous promise


【解决方案1】:

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

  1. 在这里您调用 Firebase,.once(...) 返回一个不是 await-ed 的承诺,因此稍后解决,getMain 已返回
  2. 由于promise不是await-ed,所以下一行要执行的是console.log('E2'),然后继续循环的下一次迭代
  3. 循环结束后,requests 将是一个空数组(因为值应该来自.once(...) 处理程序,但我们从未等待这些承诺)。空数组立即解析,因此Promise.all(requests) 落入then 部分,注销“E3”并解析主要承诺,有效地返回原始小部件
  4. 一旦getMain 返回,我们之前创建的 Promise 将开始在“幕后”解析和修改小部件,因此下次您尝试对小部件执行任何操作时,您可能会发现完全出乎意料的事情。

为了修复此功能,您需要等待 Firebase 返回的承诺进入底部的主要承诺 - 您可以通过将 .once() 的结果放入其中来完成调用一个新数组并在该数组上调用Promise.all(...),或者通过在循环的每次迭代中编写一个“链式”承诺,然后在循环之后立即等待它

希望有帮助!

【讨论】:

    猜你喜欢
    • 2017-06-15
    • 1970-01-01
    • 2018-02-03
    • 2018-03-05
    • 1970-01-01
    • 2020-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多