使用AngularJS进行多次api调用

时间:2017-09-04 22:19:35

标签: javascript angularjs api

我是AngularJS的新手,我正在练习下面的练习

1.使用API​​获取20个帖子并将其与用户一起显示在页面上 创建帖子并在页面上显示的姓名。 在本练习中,我使用https://jsonplaceholder.typicode.com/作为数据源。 我需要在同一个控制器中进行2次api调用

  1. 获取其中包含用户ID的20个帖子的列表(https://jsonplaceholder.typicode.com/posts

  2. 根据以上用户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>
    

2 个答案:

答案 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);
                });
        }
    });
});