AngularJS Ctrl As 服务语法

AngularJS Ctrl As Syntax with Services

我正在迁移我的 Angular 1.x 代码以使用更新、更优选的语法,避免使用 $scope 和使用控制器作为语法。不过,我在从服务获取数据时遇到问题。

这是我的例子:

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

myApp.controller('MainCtrl', ['$http', '$location', 'userService',
  function($http, $location, userService) {

    this.name = 'John Doe';

    // this.userData = {

    // }

    this.userData = userService.async().then(function(d) {
      return d;
    });


    console.log(this.userData);


  }
]);

myApp.service('userService', function($http) {

  var userService = {
    async: function() {
      // $http returns a promise, which has a then function, which also returns a promise
      var promise = $http.get('https://jsonplaceholder.typicode.com/users').then(function(response) {
        // The then function here is an opportunity to modify the response
        // console.log(response);
        // The return value gets picked up by the then in the controller.
        return response.data;
      });
      // Return the promise to the controller
      return promise;
    }
  };
  return userService;

});
<body ng-app="myApp">
  <div id="ctrl-as-exmpl" ng-controller="MainCtrl as mainctrl">

    <h1>Phone Numbers for {{mainctrl.name}}</h1>

    <button ng-click="">newest</button>
    <p>{{mainctrl.userData}}</p>
    <ul>
      <li ng-repeat="users in mainctrl.userData">{{users.phone}} -- {{users.email}}</li>
    </ul>
  </div>
</body>

我遇到的这个问题是,从 userService.async 返回的数据是一个我似乎无法向下钻取以获取数据的对象,因为该数据是 $ 的子项$state,在视图中好像不能用。

如果这不是在 Controller As/$scope-less 语法中使用服务的正确方法,那么正确的方法是什么?

现场示例:http://plnkr.co/edit/ejHReaAIvVzlSExL5Elw?p=preview

this.userData = userService.async().then(function(d) {
  return d;
});

在这段代码中 this.userData 实际上被定义为一个承诺。如果您想要正在 returned 的数据,您需要使用 .then function 中的 d 参数,如下所示:

userService.async().then(function(d){
    this.userData = d;
    //a console.log() here would determine if you are getting the data you want.  
});

编辑 我刚刚在您的服务中注意到您已经在响应对象上使用了 .data

老实说,我给你最好的建议就是 return 来自你服务内部的 http.get() 调用的承诺,如下所示:

myApp.service('userService', function($http) {
    var userService = {
        async: function() {
          return $http.get('https://jsonplaceholder.typicode.com/users');
        }
    };
    return userService;

});

然后您可以使用类似这样的方法来捕获和利用响应数据:

userService.async().then(function(response){
    this.userData = response.data;
);

这可能是一个更简洁的解决方案

您错过了 promise 的一个重要部分 - 当您 return 来自 promise 的一个值时,您 return 一个将解析为该值的新 promise。

当前将数据return从承诺设置为控制器中局部变量的方法是这样的:

myApp.controller('MainCtrl', ['$http', '$location', 'userService',
  function($http, $location, userService) {

    this.name = 'John Doe';

    userService.async().then(function(d) {
      this.userData = d;
    });
  }
]);

但是现在您因为 this 的范围而陷入困境,因此通常为控制器 this 范围使用 "placeholder" 变量。

myApp.controller('MainCtrl', ['$http', '$location', 'userService',
  function($http, $location, userService) {

    var $ctrl = this; // Use $ctrl instead of this when you want to address the controller instance

    $ctrl.name = 'John Doe';

    userService.async().then(function(d) {
      $ctrl.userData = d;
    });
  }
]);