使用 geofire 和 firebase 遍历数组时重复数据

Repeating data when looping through array using geofire and firebase

请看一下我的代码。

  var posts = PostsData.getPosts();   
  var postFunc = function(key) {
      return posts[key];  
  }

  $scope.$watch($scope.active, function() {
      $timeout(function() {
    var markers = [];

    for (var key in posts) {

          console.log(key);
          var p = gf.get(key).then(function(location) { 
          var post = postFunc(key);
          console.log(key);
          return ({
            idKey: key,
            title: post.title,
            coords: {
              latitude: location[0],
              longitude: location[1]
            }
           });
      });
      markers.push(p);

    }

    $q.all(markers).then(function(markers) {
    $scope.markers = markers;
    });

  });
})

}

循环内有两行"console.log(key)"。 第一个 console.log 打印作为唯一键的数据的准确表示。第二个 console.log 打印重复的相同数据,这是不准确的。我无法理解为什么会这样。

非常感谢您的帮助。

从第二个 console.log(key) 开始,您具有相同的值是很正常的。原因是您的异步​​函数 gf.get(key).then(function(location) { .. }。调用此函数时,您的循环已完成执行,并且 key 的值是循环 中的最后一个值。我不确定 gf.get 做了什么,但是如果 posts 是一个数组,你可以在递归的帮助下实现你的结果,如下所示

var posts = PostsData.getPosts();   
var postFunc = function(key) {
    return posts[key];  
}

var markers = [];
var getMarkers(key) {

    if (key > posts.length - 1) {

        // promise resolved for each item in posts
        $q.all(markers).then(function(markers) {
            $scope.markers = markers;
        }

        return;
    }

    console.log(key);
    gf.get(key).then(function(location) {
        var post = postFunc(key);
        console.log(key);
        markers.push({
            idKey: key,
            title: post.title,
            coords: {
                latitude: location[0],
                longitude: location[1]
            }
        });

        getMarkers(++key);
    });
}

$scope.$watch($scope.active, function() {
    markers = [];
    getMarkers(0);
});

注意: 在这种方法中,我们等待每个 promise 得到解决,然后再转到 gf.get

的下一次调用

解决该问题的另一种方法是使用 IIFE 闭包。

var markers = [];

for (var key in posts) {
    //IIFE closure
    (function (key) {
        console.log(key);
        var p = gf.get(key).then(function(location) { 
            var post = postFunc(key);
            console.log(key);
            return ({
                idKey: key,
                title: post.title,
                coords: {
                    latitude: location[0],
                    longitude: location[1]
                }
            });
        });
        markers.push(p);
    })(key);
}

通过使用 IIFE (Immediately Invoked Function Expression),每个 key 的值都会被保留,直到 .then 方法中的函数完成。