【问题标题】:Wait function with promise to end承诺结束的等待功能
【发布时间】:2018-05-20 20:23:33
【问题描述】:

我正在尝试从 firebase 获取集合,然后调用将插入数据的函数。问题是在比较函数结束之前调用了插入数据...

这是我正在遵循的指南:

1 - 获取游戏输入并创建一个包含要推荐视频的数组

2 - 从用户那里获取已经推荐的视频

3 - 将视频与数组进行比较以排除重复项。

4 - 继续执行下一个函数以将数组插入到 firebase。

问题是对于第 4 步,我需要完成第 3 步。但这并没有发生。关于如何解决这个问题的任何建议?

export const generateRecommendationsFromGame = (participantID) => {
  var newRec = [];
  let userRef = firebase.firestore().collection("users").doc(participantID);


  //1 Game inputs
  return firebase.firestore().collection("inputGame").where("user", "==", userRef).onSnapshot({}, function(querySnapshot) {
    querySnapshot.forEach(function(doc) {
      let consagua = doc.data().consagua;
      let enfart = doc.data().enfartamento;
      let mastig = doc.data().mastigacao;
      let mexdorm = doc.data().mexerdormir;
      let emoc = doc.data().emocoes;

      //13
      //V2.3.2
      if (Number(consagua) >= 3) {
        newRec.push('V2.3.2');
      }
      //15
      //V3.1
      if (Number(enfart) >= 25) {
        newRec.push('V3.1');
      }
      //16
      //V3.2
      if (Number(mastig) >= 40) {
        newRec.push('V3.2');
      }
      //17
      //V3.3
      //18
      //V3.4
      if (Number(mexdorm) >= 3) {
        newRec.push('V3.3');
        newRec.push('V3.4');
      }
      //19
      //V3.5
      if (Number(emoc) >= 2) {
        newRec.push('V3.5');
      }


      //2 - User Videos
      return firebase.firestore().collection("recommendedVideo").where("user", "==", userRef).get().then(result2 => {
        result2.forEach(doc2 => {

          //3 - Get video ref to compate to Array
          var videoFef = doc2.data().video.id;
          firebase.firestore().collection("videos").doc(videoFef).get().then(
            function(doc2) {
              if (doc2.exists) {
                var sequence = doc2.data().sequenceNumberID;
                for (var i = 0; i < newRec.length; i++) {
                  if (String(sequence) == String(newRec[i])) {
                    var index = newRec.indexOf(newRec[i]);
                    if (index > -1) {
                      newRec.splice(index, 1);
                    }
                  }
                }
              } else alert("Não existe doc videos");
            }
          )
        });
      }).then(() => {
         insertData(newRec);
      })
    });
  })
};

然后,在比较视频并排除重复的视频后,我想调用一个函数将视频插入 Firebase。

export const insertData= (arr) => {   
  var newRec = arr.split(',');
  for (var i = 0; i < newRec.length; i++) {
    var ref = newRec[i];
    firebase.firestore().collection("videos").where("sequenceNumberID", "==", ref.toString()).onSnapshot(function (querySnapshot) {
      querySnapshot.forEach(function (doc) {
        firebase.firestore().collection("recommendedVideo").add({
          seen: false,
          user: firebase.firestore().collection('users').doc(participantID),
          video: firebase.firestore().collection('videos').doc(doc.id)
        }).catch(function (error) {
          alert(error);
        })
      });
    });
  }
}

【问题讨论】:

  • 第一个sn-p完成后你在哪里打电话insertData?
  • 在第 3 步这样结束后立即调用它。 .then(() => { insertData(newRec); })
  • right after the step 3 ends 代码具体在哪里,我没看到?
  • 已编辑。我从代码中删除了,因为它不起作用。

标签: javascript firebase google-cloud-firestore


【解决方案1】:

您需要对每个doc2 进行异步查询,然后在完成所有查询后继续查询insertData。正确的工具是Promise.all,它接受一组promise,并在数组中的所有promise 都被解析后解析。因此,将每个 doc2 映射到一个 Promise。

除了Promise.all,使用async/await可以大大减少你的缩进地狱。

请注意,您在 forEach 中隐藏(复制)doc2 变量,这很容易引起混淆 - 最好将其命名为其他名称(例如 doc3):

使querySnapshot.forEach异步:

querySnapshot.forEach(async (doc) => {

然后:

//2 - User Videos
const result2 = await firebase.firestore().collection("recommendedVideo").where("user", "==", userRef).get();
await Promise.all(result2.map(async (doc2) => {
  //3 - Get video ref to compate to Array
  const videoFef = doc2.data().video.id;
  const doc3 = await firebase.firestore().collection("videos").doc(videoFef).get();
  if (!doc3.exists) {
    alert("Não existe doc videos");
    return;
  }
  var sequence = doc3.data().sequenceNumberID;
  for (var i = 0; i < newRec.length; i++) {
    if (String(sequence) !== String(newRec[i])) return;
    var index = newRec.indexOf(newRec[i]);
    if (index > -1) newRec.splice(index, 1);
  }
}));
// end of Promise.all
insertData(newRec);

【讨论】:

  • 嗨。感谢您的回答。在我调用 Promise.all 后,它停止了。我设置了一个警报,它说 //3 并且没有弹出。有什么建议吗?
  • 任何控制台错误? result2 是否被正确定义为数组?
  • 警报类型显示它是一个对象。应该是对象还是数组?
  • 数组是对象。如果result2 不是数组,则在调用map 时应该会出错。你可以用Array.isArray来检查是否是一个数组,但是控制台应该足够了。
  • 我在控制台上得到了这个。 TypeError: undefined is not a function (evalating 'result2.map')
【解决方案2】:

这是我设法解决这个问题的方法。

        var reads = [];

        await firebase.firestore().collection("recommendedVideo").where("user", "==", userRef).onSnapshot({}, function (querySnapshot) {
            querySnapshot.forEach(async doc => {
                reads.push(doc);
            })
            return Promise.all(reads.map(async (doc1) => {
                //3 - Get video ref to compate to Array
                const videoFef = doc1.data().video.id;
                const doc3 = await firebase.firestore().collection("videos").doc(videoFef).get();
                if (!doc3.exists) {
                    alert("Não exisste doc videos");
                    return;
                }

                var sequence = doc3.data().sequenceNumberID;
                for (var i = 0; i < newRec.length; i++) {
                    if (String(sequence) == String(newRec[i])) {
                        var index = newRec.indexOf(newRec[i]);
                        if (index > -1) {
                            newRec.splice(index, 1);
                        }
                    }
                }
            })).then(function() {
                insertData(newRec, participantID);
            });
        });

感谢CertainPerformance 的帮助。

【讨论】:

    猜你喜欢
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 2023-04-08
    • 2021-10-10
    相关资源
    最近更新 更多