【问题标题】:For loop adds elements to array succesfully but returns empty array afterFor循环成功将元素添加到数组,但之后返回空数组
【发布时间】:2016-03-13 18:07:17
【问题描述】:

所以这段代码成功运行并将元素添加到数组中,这通过将它们记录到控制台来确认,但是之后,当我返回数组时,它返回为空。整个早上我一直在用头撞墙。

details.getDetails = function(idSet, pageNum) {
      var page = idSet[pageNum],
          placeDetails = [],
          i;

      for(i=0; i<page.length; i++){
        ngGPlacesAPI.placeDetails({placeId: page[i]})
          .then(function(data){
            response = data;
            placeDetails.push(response);
            console.log(placeDetails) //This shows the loop running and the array being populated
          })
      }
      return placeDetails;
      console.log(placeDetails) //This returns empty array 
    };

我确实认为问题可能与 Rayon 提到的异步数据有关,我试图返回一个承诺,但我不确定我做得对。这是我尝试过的代码。

.factory('details', function(ngGPlacesAPI, $q){
    var response,
        details = {};

 details.getDetails = function(idSet, pageNum) {
      var page = idSet[pageNum],
          deferred = $q.defer,
          placeDetails = [],
          i;

      for(i=0; i<page.length; i++){
        ngGPlacesAPI.placeDetails({placeId: page[i]})
          .then(function(data){
            response = data;
            placeDetails.push(response);
          })
      }
      deferred.resolve(placeDetails);
      console.log(deferred.promise);
      return deferred.promise;
    };

    // Return Details Object
    return details;
  });

【问题讨论】:

  • 你正在处理asynchronous事件..
  • 为什么投反对票?我知道我做错了什么,这就是我问的原因。

标签: javascript arrays angularjs for-loop


【解决方案1】:

这里的问题是 .placeDetails 立即返回,因此 for 循环在您实际检索到一些数据之前就已经完成了很长时间。这就是为什么在这里使用 Promise 并不能真正帮助您,因为 resolve 调用几乎会立即被调用。

我建议查看 $q.all 以等待您对 placeDetails 的所有调用都已完成,然后再解决您的承诺。

这样的(未经测试的)代码应该适合您。它可能需要一些更改,但它应该会给你一个想法。

details.getDetails = function(idSet, pageNum) {
      var page = idSet[pageNum],
          placeDetails = [],
          mainDeferred = $q.defer(),
          promises = [];

      for(var i=0; i<page.length; i++){
        var deferred = $q.defer();
        ngGPlacesAPI.placeDetails({placeId: page[i]})
          .then(function(data){
            placeDetails.push(data);
            deferred.resolve();
          });
        promises.push(deferred.promise);
      }
    $q.all(promises).then(function() {
       mainDeferred.resolve(placeDetails); 
    });
    return mainDeferred;
  });

【讨论】:

  • 感谢您的回复。我运行了上面的代码,它创建了一组承诺,然后返回一个承诺,但是当我尝试在控制器中使用此代码 details.getDetails(page, pageNum).then(function(response){ vm.restaurants = response; console.log(vm.restaurants); }); 使用它时,我没有将任何内容记录到控制台,但我也没有得到任何错误。
  • @GrantJordan 正如我所说的那样;我给你的代码是给你一个一般的想法,而不是一个银盘上的解决方案:-)你可能需要做一些调试才能让事情正常工作。例如;不要使用全局数组,而是在解析函数中传递.placeDetails() 的结果,然后将所有结果的值添加到$q.all() 中。您可以查看github.com/kriskowal/q/wiki/API-Reference#promiseall 了解有关 all() 函数的更多信息。
  • 非常感谢您让我走上正轨。稍作调整,我就让一切都运行起来了。
猜你喜欢
  • 2019-09-09
  • 1970-01-01
  • 2021-04-22
  • 2019-04-02
  • 2018-12-08
  • 2017-07-28
  • 1970-01-01
  • 2016-10-20
  • 2021-05-24
相关资源
最近更新 更多