从 Firebase 读取完成后返回数组 [英] returning array after finish reading from Firebase

查看:21
本文介绍了从 Firebase 读取完成后返回数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to push all values that satisfy a certain condition to an array then return this array. Here's my code

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 后如何返回正确的数组?

However since forEach is asynchronous, and it seems like I cannot use a callback on forEach, the listOfItems I return would just be an empty array. I have also tried ".then", but it would only allow me to do more stuff inside ".then" and I would like to return this array as a variable to other parts of the code. How can I return the correct array after forEach has been executed?

推荐答案

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

It's not the forEach that is async (JavaScript, Node.js: is Array.forEach asynchronous?), it's the query.once("value"). You can solve this problem in a variety of ways. With callbacks, promises, or await/async.

我建议阅读这个内容丰富的答案,其中包含更多更好的示例:如何从异步调用返回响应?

I suggest reading this very informative answer that covers much more with better examples: How do I return the response from an asynchronous call?

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

The idea here is to provide a function that can be called with the result once the asynchronous work is done, but after our work in forEach is complete.

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);
});

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

Promises are another way to handle asynchronous code. I suggest reading about them here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises. It will explain them far better than I could.

这是您使用 Promise 的代码:

Here is your code using promises:

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 之后触发一次.我们可以像这样将它们链接在一起.

This can actually be simplified further as it appears query.once returns a promise itself. We can simply return the promise provided to us by query.once which will fire once after the .then of your internal function. We can chain them together like so.

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);
});

这篇关于从 Firebase 读取完成后返回数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆