在Controller

时间:2015-06-17 06:11:15

标签: angularjs http foreach

http://codepen.io/rcidaleassumpo/pen/eNEjGY?editors=001   这是代码的链接。  下面我首先使用forEach将昵称与基本链接结合起来,这样我就可以通过$ http获取fullLink来进行调用。但是当我尝试拨打电话并发布到一个空阵列时,事情并没有像我预期的那样发挥作用,这就是我需要你帮助的原因。

根据我的理解,我可以从$ http请求获得的信息,不会自行保留请求,并且信息数组保持为空。

var app  = angular.module('myApp', []);

app.controller('mainController', function($scope, $http){
  $scope.channels = ["freecodecamp", "storbeck", "terakilobyte", "habathcx","RobotCaleb","comster404","brunofin","thomasballinger","noobs2ninjas","beohoff"];
  var url = 'https://api.twitch.tv/kraken/channels/';
  $scope.fullLinks = [];
  $scope.infos = [];
  $scope.channels.forEach(function(channel){
      $scope.data = '';
      var link = url + channel + '?callback=JSON_CALLBACK';
      $scope.fullLinks.push(link);
  });
  $scope.fullLinks.forEach(function(link){
      $http.jsonp(link).success(function(data){
         var obj = {}
         obj.url = data.url;
        $scope.infos.push(obj);
      });
  });
  console.log($scope.infos);

});

4 个答案:

答案 0 :(得分:4)

您正在尝试记录$scope.infos而不等待请求完成并将加载的响应数据推送到阵列。

这里的答案是使用Promises在所有请求解析并推送各自的数据后提供回调:

app.controller('mainController', function($scope, $http, $q) {

    var url = 'https://api.twitch.tv/kraken/channels/';

    $scope.channels = ["freecodecamp", "storbeck", "terakilobyte", "habathcx", "RobotCaleb", "comster404", "brunofin", "thomasballinger", "noobs2ninjas", "beohoff"];

    $scope.infos = [];

    $scope.fullLinks = $scope.channels.map(function(channel) {
        return url + channel + '?callback=JSON_CALLBACK';
    });

    $q.all($scope.fullLinks.map(function(url) {
        return $http.jsonp(url).success(function(data) {
            $scope.infos.push({
                url: data.url
            });
        });
    })).then(function() {
        console.log($scope.infos);    
    });

});

$q.all的其他略有不同的变体:

$q.all($scope.fullLinks.map($http.jsonp)).then(function(responses) {
    return responses.map(function(response) {
        return {
            url: response.data.url,
            status: response.data.status
        };
    });   
}).then(function(data) {
    $scope.infos = data;
});

为了更好地理解这个问题,请查看这个非常受欢迎的问题:How do I return the response from an asynchronous call?

以下是您的代码演示:http://plnkr.co/edit/uhW6eyTMsSvxlLCoHwQ8?p=preview

答案 1 :(得分:1)

问题是jsonp是异步的。结果会返回给您,但是在您调用console.log($scope.infos);

之后它们会到达

您需要确保仅在每个查询完成后处理结果。

我会用承诺来解决这个问题。

var promises = $scope.fullLinks.map(function(link){
  return new Promise(function(resolve, reject) {
     console.log('Invoking ' + link);
     $http.jsonp(link).success(function(data){
        console.log('Call to ' + link + 'returned successfully');
        var obj = {}
        obj.url = data.url;
        $scope.infos.push(obj);
        resolve();
     }).
     error(function() {
       // In this example, I'm just failing silently
       // You could also call reject() if you 
       // want the failure to propogate to the caller
       console.log('Call to ' + link + 'failed');
       resolve(); 
     });
  });
});
Promise.all(promises).then(function() {
   console.log('All calls have completed');

   console.log($scope.infos);
});

答案 2 :(得分:0)

你不能指望console.log($ scope.infos);将打印包含所有项目的数组,因为http请求是异步的,并且console.log可能在任何http请求返回结果之前执行

$scope.fullLinks.forEach(function(link){
  $http.jsonp(link).success(function(data){
     var obj = {}
     obj.url = data.url;
     console.log(obj); //will show what request have returned
     $scope.infos.push(obj);
     console.log($scope.infos.length); // will show how array change size
  });

});

你应该看到数组会增长,一切正常

答案 3 :(得分:0)

只有当您从服务器获得所需的响应时,才需要执行逻辑。你现在正在做的是:

  • 请求。
  • 用它做点什么。
  • 从服务器收到您的回复。

你真正想要的是:

  • 请求。
  • 从服务器收到您的回复。
  • 用它做点什么。

这就是我们使用Promises的原因。 如果您将http请求移到服务中,我认为更容易获得正在发生的事情。

app
 // create a service for all your http calls
.service('getChannels', function($http) {
  var url = 'https://api.twitch.tv/kraken/channels/'
    , qs = '?callback=JSON_CALLBACK';

  // $http returns a Promise, so if we return $http.get() we will
  // be able to chain the response with .then(), .catch() and .finally()
  this.query = function (channel) {
    return $http.get(url + channel + qs);
  }
})
// inject the service in your controller (see getChannels here below)
.controller('mainController', function($scope, getChannels){

  $scope.channels = ["freecodecamp", "storbeck", "terakilobyte", "habathcx","RobotCaleb","comster404","brunofin","thomasballinger","noobs2ninjas","beohoff"];

  $scope.infos = [];

  // angular provides a $q.all method for when you need more 
  // than one response and do something with each one when they 
  // are finished. 
  // We .map the channels and return a Promise for each of them.
  // With "$q.all" and ".then" we know *for sure* that our function
  // will execute only when we have the response in our hands,
  // and never before
  $q.all($scope.channels.map(function (channel) {
    return getChannels.query(channel);
  // handle your response here, "response" will contain all your http responses.
  })).then(function(response) {
    response.forEach()function (data) {
      var obj = {};
      obj.url = data.url;
      $scope.infos.push(obj);
    };
    console.log($scope.infos);

  // remember to take care of errors, ".catch" does just that
  }).catch(handleYourError);


});

了解许多(错误和正确)处理承诺的方法非常重要。一旦你了解它们,你的控制器将变得更轻,http请求将不再是麻烦。 Here's我认为这是一篇非常容易理解的关于此事的文章。