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);
});
答案 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我认为这是一篇非常容易理解的关于此事的文章。