【问题标题】:returning array after finish reading from Firebase从 Firebase 读取完成后返回数组
【发布时间】:2023-03-29 05:50:01
【问题描述】:

我想将满足某个条件的所有值推送到一个数组中,然后返回这个数组。这是我的代码

exports.getNearbyPosts = function (myLat, myLng){
  var query = firebase.database().ref("posts/").orderByKey();
  var listOfItems = [];
  query.once("value")
    .then(function(snapshot) {
      snapshot.forEach(function(childSnapshot) {
        var key = childSnapshot.key;
        var childData = childSnapshot.val();
        var dist = getDistanceBetweenCoord(childData.lat, childData.lng, myLat, myLng);
        if(dist < 10239820938502){
          listOfItems.push(childSnapshot);
        }
    });
  });

  return listOfItems;
}

但是,由于 forEach 是异步的,而且似乎我不能在 forEach 上使用回调,所以我返回的 listOfItems 将只是一个空数组。我也尝试过“.then”,但它只会让我在“.then”中做更多的事情,我想将此数组作为变量返回给代码的其他部分。 forEach 执行后如何返回正确的数组?

【问题讨论】:

    标签: javascript firebase asynchronous firebase-realtime-database


    【解决方案1】:

    异步的不是forEach (JavaScript, Node.js: is Array.forEach asynchronous?),而是query.once("value")。您可以通过多种方式解决此问题。使用回调、承诺或等待/异步。

    我建议阅读这个内容丰富的答案,其中包含更多更好的示例:How do I return the response from an asynchronous call?

    带有回调

    这里的想法是提供一个函数,一旦异步工作完成,但在我们在forEach 的工作完成之后,就可以使用结果调用该函数。

    exports.getNearbyPosts = function (myLat, myLng, callback){
      var query = firebase.database().ref("posts/").orderByKey();
      var listOfItems = [];
      query.once("value").then(function(snapshot) {
        snapshot.forEach(function(childSnapshot) {
          var key = childSnapshot.key;
          var childData = childSnapshot.val();
          var dist = getDistanceBetweenCoord(childData.lat, childData.lng, myLat, myLng);
          if(dist < 10239820938502){
            listOfItems.push(childSnapshot);
          }
        });
        callback(listOfItems)
      });
    }
    
    getNearbyPosts(0, 0, (result) => {
      console.log(result);
    });

    承诺(ES2016)

    Promises 是处理异步代码的另一种方式。我建议在这里阅读它们https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises。它会比我更好地解释它们。

    这是您使用 Promise 的代码:

    exports.getNearbyPosts = function (myLat, myLng){
      var query = firebase.database().ref("posts/").orderByKey();
      var listOfItems = [];
      return new Promise((resolve, reject) => {
        query.once("value").then(function(snapshot) {
          snapshot.forEach(function(childSnapshot) {
            var key = childSnapshot.key;
            var childData = childSnapshot.val();
            var dist = getDistanceBetweenCoord(childData.lat, childData.lng, myLat, myLng);
            if(dist < 10239820938502){
              listOfItems.push(childSnapshot);
            }
          });
          resolve(listOfItems);
        });
      });
    }
    
    getNearbyPosts(0, 0).then(result => {
      console.log(result);
    });

    这实际上可以进一步简化,因为 query.once 本身返回了一个承诺。我们可以简单地返回由query.once 提供给我们的承诺,它将在您的内部函数的.then 之后触发一次。我们可以像这样将它们链接在一起。

    exports.getNearbyPosts = function (myLat, myLng){
      var query = firebase.database().ref("posts/").orderByKey();
      var listOfItems = [];
      
      // We return the promise created by query.once
      return query.once("value").then((snapshot) => {
      
        // our inital .then will do some data filtering
        snapshot.forEach((childSnapshot) => {
          var key = childSnapshot.key;
          var childData = childSnapshot.val();
          var dist = getDistanceBetweenCoord(childData.lat, childData.lng, myLat, myLng);
          if(dist < 10239820938502){
            listOfItems.push(childSnapshot);
          }
        });
        
        // We return here to continue the chain. The next .then that picks this up will have this result
        return listOfItems;
      });
    }
    
    // Our last promise resolution in the chain, containing listOfItems
    getNearbyPosts(0, 0).then(result => {
      console.log(result);
    });

    【讨论】:

    • 很好的答案德文!仅供参考。 Snapshot 不完全是 Array,但 Snapshot.forEach() 确实也是同步的。
    • 啊,不是这样的! firebase.google.com/docs/reference/js/…。很高兴知道,感谢您的信息。
    猜你喜欢
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-25
    • 2021-08-10
    相关资源
    最近更新 更多