我是AngularJS的新手,我正在练习下面的练习
1.使用API获取20个帖子并将其与用户一起显示在页面上 创建帖子并在页面上显示的姓名。 在本练习中,我使用https://jsonplaceholder.typicode.com/作为数据源。 我需要在同一个控制器中进行2次api调用
获取其中包含用户ID的20个帖子的列表(https://jsonplaceholder.typicode.com/posts)
根据以上用户ID我需要获取用户名(https://jsonplaceholder.typicode.com/users/userId) 请看我在plnkr中完成的工作,我能够显示Post但不能显示用户名。
的script.js
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
$http.get("https://jsonplaceholder.typicode.com/posts").then(function(response) {
$scope.data = response.data;
var postList = [];
for (var i = 0; i < 20; i++) {
var display = {
UserName: $http.get("https://jsonplaceholder.typicode.com/users/" + $scope.data[i].userId).then(function(response) {
$scope.user = response.data;
}),
Post: $scope.data[i].title
}
postList.push(display);
}
$scope.list = postList;
});
});
的index.html
<div ng-repeat="x in list">
Post:{{ x.Post }}
UserName:{{x.UserName}}
</div>
答案 0 :(得分:1)
我认为这方面是错误的:
.then(function(response) {
$scope.data = response.data;
var postList = [];
for (var i = 0; i < 20; i++) {
var display = {
UserName: $http.get("https://jsonplaceholder.typicode.com/users/"+$scope.data[i].userId).then(function(response){
$scope.user = response.data;
}),
Post: $scope.data[i].title
}
postList.push(display);
}
$scope.list = postList;
});
您在Promise object
媒体资源中存储了UserName
,并产生了意外结果。
更正请求完成后分配postList:
.then(function(response) {
$scope.data = response.data;
var postList = [];
for (var i = 0; i < 20; i++) {
$http.get("https://jsonplaceholder.typicode.com/users/"+$scope.data[i].userId).then(function(response){
$scope.user = response.data;
var display = {
UserName: "",
Post: $scope.data[i].title
};
$scope.list.push(display);
});
}
$scope.list = postList;
});
实施此操作后,您将遇到一个新问题:
因为您在循环中调用了$http.get()
并且在i
执行.then()
时实际使用了变量.then()
,因此i
的值已经在其最终形式为i = 20 | data.length
,每.then()
个来电都会收到。
为了克服这个问题,我知道的最好的方法是在显示之前先格式化整个数据:
$http.get("https://jsonplaceholder.typicode.com/posts")
.then(function(response)
{
var data = response.data;
var postList = [];
// this will check if formatting is done.
var cleared = 0;
// create a function that checks if data mapping is done.
var allClear = function () {
if (postList.length == cleared)
{
// display the formatted data
$scope.list = postList;
}
};
for (var i = 0; i < data.length; i++)
{
// create a object that stores the necessary data;
var obj = {
// the ID will be needed to store name;
ID: data[i].userId,
Post: data[i].title,
UserName: ""
};
var url = "https://jsonplaceholder.typicode.com/users/" + obj.userId;
$http.get(url).then(function(response)
{
// find its entry in the array and add UserName;
postList.forEach(function (item)
{
if (item.ID == response.userId)
{
// just add the correct key, but I will assume it is `userName`
item.UserName = response.userName;
// break the loop
return item;
}
});
// increment cleared
cleared++;
// call allClear
allClear();
});
postList.push(obj);
}
}
);
通过这种方式,我们可以确保数据在视图中显示之前已完成。
由于此解决方案包含a loop
以将结果与其原始对象进行映射,因此我们实际上可以将postList
更改为对象以使其更快一些:
// var postList = [];
var postList = {};
// instead of pushing we will use the ID as key
// postList.push(obj);
postList[obj.ID] = obj;
以及本节中的内容:
$http.get(url).then(function(response)
{
// instead of looking for the item in .forEach
postList[response.userId].userName = response.userName;
// increment cleared
cleared++;
// call allClear
allClear();
});
希望有所帮助。
答案 1 :(得分:1)
简单的解决方案是将用户名添加到用户对象,然后在解析承诺时将其推送到范围列表
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
$http.get("https://jsonplaceholder.typicode.com/posts").then(function(response) {
$scope.data = response.data;
$scope.list = [];
for (var i = 0; i < 20; i++) {
$http.get("https://jsonplaceholder.typicode.com/users/" + $scope.data[i].userId)
.then(function(response) {
var user = {
UserName: response.data.username,
Post: $scope.data[i].title
}
$scope.list.push(user);
});
}
});
});