JavaScript (angular) 中的承诺
Promise in JavaScript (angular)
我对 angular 和 http 调用还很陌生。
然后我读了一些关于 Promise to ync calls 的内容。我根本无法理解。
所以我需要一些帮助才能知道我是否在朝着正确的方向前进。
我正在编写一个 API 用于获取视频,以及有关它们的详细信息(观看次数等)的 Youtube API v3。
但是我似乎在获取详细信息时出错,因为我的数组一直都是空的。
/*var promises = [];*/ // PROMISE
var videometrics;
var videodetails = [];
var deferred = $q.defer();
$http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=' + playlistId + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function (response) {
for (var i = 0; i < response.items.length; i++) {
var video = {
id: response.items[i].snippet.resourceId.videoId,
title: response.items[i].snippet.title
};
$scope.video.push(video)
}
/*console.log($scope.video)
var promises = [];*/
for (i = 0; i < $scope.video.length; i++) {
/*console.log("looping")
console.log($scope.video)
console.log("Vi henter fra id:")
console.log($scope.video[i].id)*/
$http.get('https://www.googleapis.com/youtube/v3/videos?part=statistics&id=' + $scope.video[i].id + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function (responsevideo) {
/*console.log($scope.video[i].id);*/
// console.log("we are in the metric loop")
// console.log($scope.video[i].id)
// console.log($scope.video[i].title)
// console.log(responsevideo)
videometrics = {
id: responsevideo.items[0].id,
views: responsevideo.items[0].statistics.viewCount,
likes: responsevideo.items[0].statistics.likeCount,
dislikes: responsevideo.items[0].statistics.dislikeCount,
favorites: responsevideo.items[0].statistics.favoriteCount,
comments: responsevideo.items[0].statistics.commentCount
};
videodetails.push(videometrics);
deferred.resolve(responsevideo);
/*detailsOnVideos = $scope.videometrics;*/
})
/* videodetails.push(videometrics);*/
}
/*promises.push(videodetails);*/ // PROMISE
console.log(videodetails);
/* console.log(promises);*/ //PROMISE LOGGER
/* console.log(videodetails);*/
console.log($scope.video);
console.log("")
pagetokenarr = response.nextPageToken;
console.log(pagetokenarr)
});
return deferred;
/*return $q.all(promises);*/ // PROMISE
如您所见,我的第一个 http get 是有效的,但下一个不是。我不明白为什么。但是,如果我将我的 videodetails 数组推入一个 promise 数组,它就可以工作。然后再次。我不知道为什么。
您的代码似乎工作正常。我删除了除必需品以外的所有内容,添加了我需要的变量作为占位符,因为我不确定 playlistId 等。这是我测试过的代码。
var app = angular.module('app', []);
app.controller('ctrl', function ($scope, $http) {
var videometrics;
$scope.videodetails = [];
var playlistId = "PL63F0C78739B09958";
$scope.video = [];
$http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=' + playlistId + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function (response) {
for (var i = 0; i < response.items.length; i++) {
var video = {
id: response.items[i].snippet.resourceId.videoId,
title: response.items[i].snippet.title
};
$scope.video.push(video);
}
for (i = 0; i < $scope.video.length; i++) {
$http.get('https://www.googleapis.com/youtube/v3/videos?part=statistics&id=' + $scope.video[i].id + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function (responsevideo) {
var videometrics = {
id: responsevideo.items[0].id,
views: responsevideo.items[0].statistics.viewCount,
likes: responsevideo.items[0].statistics.likeCount,
dislikes: responsevideo.items[0].statistics.dislikeCount,
favorites: responsevideo.items[0].statistics.favoriteCount,
comments: responsevideo.items[0].statistics.commentCount
};
$scope.videodetails.push(videometrics);
});
}
});
});
这将在范围内可用时使用 {{videodetails}} 在浏览器中显示。
如果您需要处理数据而不是仅仅显示数据,您可能需要使用其他答案建议的服务。
$http 不需要 $q。基本上有两种方法(据我所知)可以使用 $http:
1) 创建一个服务,在那里隔离 $http。 Return 这样的承诺:
return $http.get({params...}).then(function(data) {
return data.result;
});
然后在控制器中你将拥有:
SuperService.get(params...).then(function(data) { $scope.something = data; });
2) 数据绑定!做一个服务,把 $http 放在那里。但是这次您将结果绑定到服务内的一个对象。在该服务中,您还有一个 return 该对象的方法。
$http.get({params...}).then(function(data) {
myObject = data.result;
});
然后在控制器中:
$scope.spiderman = SuperService.getObj();
SuperService.get(params...);
当您调用 .get() 时,AngularJS 发挥它的魔力并更新 $scope.spiderman(当然,一旦您收到服务器的响应)。
相关文献:
这是一个适用于此 plunker
的解决方案
您的代码运行良好。问题是你的 console.log()
被解雇得太早了,因为它不在你的承诺的 .success()
或 .then()
中。它在 $http
调用解决之前被触发。
我修改了一些你的代码(特别是论文 for
循环)以使其更具可读性。
此外,在 $http
调用 return promises
之前,您不需要构建自己的 promise
这是最终代码:
$http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=' + playlistId + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function (response) {
angular.forEach(response.items, function(item){
var video = {
id: item.snippet.resourceId.videoId,
title: item.snippet.title
};
$scope.video.push(video);
})
console.log($scope.video);
angular.forEach($scope.video, function(video){
httpcalls.push($http.get('https://www.googleapis.com/youtube/v3/videos?part=statistics&id=' + video.id + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function (responsevideo) {
videometrics = {
id: responsevideo.items[0].id,
views: responsevideo.items[0].statistics.viewCount,
likes: responsevideo.items[0].statistics.likeCount,
dislikes: responsevideo.items[0].statistics.dislikeCount,
favorites: responsevideo.items[0].statistics.favoriteCount,
comments: responsevideo.items[0].statistics.commentCount
};
$scope.videodetails.push(videometrics);
}));
});
pagetokenarr = response.nextPageToken;
$q.all(httpcalls).then(function(){
console.log($scope.videodetails);
})
});
请注意,我将所有 $http
调用放入一个集合 (httpcalls
) 并将您的 console.log 包装到 $q.all(httpcalls).then()
函数中。这将等到对集合的所有 $http
调用都已解决。
希望对您有所帮助。
我对 angular 和 http 调用还很陌生。
然后我读了一些关于 Promise to ync calls 的内容。我根本无法理解。 所以我需要一些帮助才能知道我是否在朝着正确的方向前进。
我正在编写一个 API 用于获取视频,以及有关它们的详细信息(观看次数等)的 Youtube API v3。
但是我似乎在获取详细信息时出错,因为我的数组一直都是空的。
/*var promises = [];*/ // PROMISE
var videometrics;
var videodetails = [];
var deferred = $q.defer();
$http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=' + playlistId + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function (response) {
for (var i = 0; i < response.items.length; i++) {
var video = {
id: response.items[i].snippet.resourceId.videoId,
title: response.items[i].snippet.title
};
$scope.video.push(video)
}
/*console.log($scope.video)
var promises = [];*/
for (i = 0; i < $scope.video.length; i++) {
/*console.log("looping")
console.log($scope.video)
console.log("Vi henter fra id:")
console.log($scope.video[i].id)*/
$http.get('https://www.googleapis.com/youtube/v3/videos?part=statistics&id=' + $scope.video[i].id + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function (responsevideo) {
/*console.log($scope.video[i].id);*/
// console.log("we are in the metric loop")
// console.log($scope.video[i].id)
// console.log($scope.video[i].title)
// console.log(responsevideo)
videometrics = {
id: responsevideo.items[0].id,
views: responsevideo.items[0].statistics.viewCount,
likes: responsevideo.items[0].statistics.likeCount,
dislikes: responsevideo.items[0].statistics.dislikeCount,
favorites: responsevideo.items[0].statistics.favoriteCount,
comments: responsevideo.items[0].statistics.commentCount
};
videodetails.push(videometrics);
deferred.resolve(responsevideo);
/*detailsOnVideos = $scope.videometrics;*/
})
/* videodetails.push(videometrics);*/
}
/*promises.push(videodetails);*/ // PROMISE
console.log(videodetails);
/* console.log(promises);*/ //PROMISE LOGGER
/* console.log(videodetails);*/
console.log($scope.video);
console.log("")
pagetokenarr = response.nextPageToken;
console.log(pagetokenarr)
});
return deferred;
/*return $q.all(promises);*/ // PROMISE
如您所见,我的第一个 http get 是有效的,但下一个不是。我不明白为什么。但是,如果我将我的 videodetails 数组推入一个 promise 数组,它就可以工作。然后再次。我不知道为什么。
您的代码似乎工作正常。我删除了除必需品以外的所有内容,添加了我需要的变量作为占位符,因为我不确定 playlistId 等。这是我测试过的代码。
var app = angular.module('app', []);
app.controller('ctrl', function ($scope, $http) {
var videometrics;
$scope.videodetails = [];
var playlistId = "PL63F0C78739B09958";
$scope.video = [];
$http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=' + playlistId + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function (response) {
for (var i = 0; i < response.items.length; i++) {
var video = {
id: response.items[i].snippet.resourceId.videoId,
title: response.items[i].snippet.title
};
$scope.video.push(video);
}
for (i = 0; i < $scope.video.length; i++) {
$http.get('https://www.googleapis.com/youtube/v3/videos?part=statistics&id=' + $scope.video[i].id + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function (responsevideo) {
var videometrics = {
id: responsevideo.items[0].id,
views: responsevideo.items[0].statistics.viewCount,
likes: responsevideo.items[0].statistics.likeCount,
dislikes: responsevideo.items[0].statistics.dislikeCount,
favorites: responsevideo.items[0].statistics.favoriteCount,
comments: responsevideo.items[0].statistics.commentCount
};
$scope.videodetails.push(videometrics);
});
}
});
});
这将在范围内可用时使用 {{videodetails}} 在浏览器中显示。
如果您需要处理数据而不是仅仅显示数据,您可能需要使用其他答案建议的服务。
$http 不需要 $q。基本上有两种方法(据我所知)可以使用 $http:
1) 创建一个服务,在那里隔离 $http。 Return 这样的承诺:
return $http.get({params...}).then(function(data) {
return data.result;
});
然后在控制器中你将拥有:
SuperService.get(params...).then(function(data) { $scope.something = data; });
2) 数据绑定!做一个服务,把 $http 放在那里。但是这次您将结果绑定到服务内的一个对象。在该服务中,您还有一个 return 该对象的方法。
$http.get({params...}).then(function(data) {
myObject = data.result;
});
然后在控制器中:
$scope.spiderman = SuperService.getObj();
SuperService.get(params...);
当您调用 .get() 时,AngularJS 发挥它的魔力并更新 $scope.spiderman(当然,一旦您收到服务器的响应)。
相关文献:
这是一个适用于此 plunker
的解决方案您的代码运行良好。问题是你的 console.log()
被解雇得太早了,因为它不在你的承诺的 .success()
或 .then()
中。它在 $http
调用解决之前被触发。
我修改了一些你的代码(特别是论文 for
循环)以使其更具可读性。
此外,在 $http
调用 return promises
这是最终代码:
$http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=' + playlistId + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function (response) {
angular.forEach(response.items, function(item){
var video = {
id: item.snippet.resourceId.videoId,
title: item.snippet.title
};
$scope.video.push(video);
})
console.log($scope.video);
angular.forEach($scope.video, function(video){
httpcalls.push($http.get('https://www.googleapis.com/youtube/v3/videos?part=statistics&id=' + video.id + '&key=AIzaSyDQv-WpATIWLinCB3H_sH4W1sKx7plyvRA')
.success(function (responsevideo) {
videometrics = {
id: responsevideo.items[0].id,
views: responsevideo.items[0].statistics.viewCount,
likes: responsevideo.items[0].statistics.likeCount,
dislikes: responsevideo.items[0].statistics.dislikeCount,
favorites: responsevideo.items[0].statistics.favoriteCount,
comments: responsevideo.items[0].statistics.commentCount
};
$scope.videodetails.push(videometrics);
}));
});
pagetokenarr = response.nextPageToken;
$q.all(httpcalls).then(function(){
console.log($scope.videodetails);
})
});
请注意,我将所有 $http
调用放入一个集合 (httpcalls
) 并将您的 console.log 包装到 $q.all(httpcalls).then()
函数中。这将等到对集合的所有 $http
调用都已解决。
希望对您有所帮助。