首页 > 解决方案 > 如何让这个 for...of 循环停止并在继续之前等待?(带有 Firestore 监听器的 JavaScript 异步/等待)

问题描述

这个函数处理一个单词数组。如果它在我们的字典中找到一个单词,它会继续查找下一个单词。如果它在我们的字典中找不到单词,它会向我们的 Firestore 数据库写入一个单词请求。然后它设置一个侦听器来侦听要写入 Firebase 数据库的单词 response。当响应被写入时,监听器被分离。这大约需要两秒钟。此代码遍历单词数组而不等待单词响应。我如何告诉它在继续下一个单词之前等待单词响应?

$scope.requestWords = function() {

  async function processWordRequests() {
    for (let word of $scope.wordsArray) {
      console.log(word);
      var doc = await firebase.firestore().collection('Dictionaries').doc($scope.longLanguage).collection("Words").doc(word).get()
      if (doc.data() === undefined) {
        console.log("Didn't find " + word + " in L2 dictionary.");

        await firebase.firestore().collection('Users').doc($scope.user.uid).collection($scope.longLanguage).doc('Word_Request').set({
          word: word,
          requestOrigin: $scope.longLanguage + ':' + $scope.movieTitle + ':' + $scope.clipInMovieModel
        })
        console.log("Requested " + word);

        await firebase.firestore().collection('Users').doc($scope.user.uid).collection($scope.longLanguage).doc('Word_Response').onSnapshot(function(doc) {
          console.log("Listening for response...");
          if (doc.data().word === word) {
            console.log(word + " added to L2 dictionary.");
            firebase.firestore().collection('Users').doc($scope.user.uid).collection($scope.longLanguage).doc('Word_Response')
            .onSnapshot(function (){
              console.log("Listener unsubscribed.")
              // How do I make it wait here before going on to the next word?
              return;
            });
          }
          else {
            console.log("Still listening...")
          }
        });

      } else {
        console.log("Found " + word + " in L2 dictionary.");
      }
    }
  }

  processWordRequests();
};

标签: javascriptasync-awaitgoogle-cloud-firestore

解决方案


您需要使用承诺或承诺您的代码。

你有这行代码:

    await firebase.firestore().collection('Users').doc($scope.user.uid).collection($scope.longLanguage).doc('Word_Response').onSnapshot(function(doc) {

右侧的哪个方式(请使用换行符以提高可读性)你有.onSnapshot(function(doc) {它我不确定但我猜它不会返回一个承诺,所以你不能等待它。

相反,你可以用一个承诺来包装它,比如......

await new Promise((resolve, reject)=> {
    firebase.firestore().collection('Users').doc($scope.user.uid).collection($scope.longLanguage).doc('Word_Response').onSnapshot(function(doc) {
    ...
    resolve("value-to-return-to-await").
    ...
});

您可以通过这个自包含的培训课程了解更多关于 Promise 的信息:https ://github.com/stevekane/promise-it-wont-hurt


推荐阅读