2016-12-14 60 views
0

我正在迁移我的Angular 1.x代码以使用避免使用$ scope并使用控制器作为语法的更新,更喜欢的语法。虽然我从服务中获取数据时遇到了问题。AngularJS Ctrl作为语法与服务

这里是我的例子:

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返回的数据是一个对象,我似乎无法深入通以获取数据,因为数据是$$状态的孩子,这在视图中似乎不能使用。

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

活生生的例子在这里:http://plnkr.co/edit/ejHReaAIvVzlSExL5Elw?p=preview

回答

1

你已经错过承诺的重要组成部分的位清洁 - 当哟你从承诺中返回一个值,你将返回一个新的承诺,将解析为这个值。

目前的方法来设置从承诺在您的控制器中的局部变量返回的数据是这样的:

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

    this.name = 'John Doe'; 

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

但现在你是在因为this范围的渔获物,所以它是很常见为控制器this范围使用“占位符”变量。

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; 
    }); 
    } 
]); 
+0

如果我注销'this'和占位符值(在我的plnkr中:http://plnkr.co/edit/KBnz7yQkyBp3B8MPFpYd?p=预览我正在使用'vm'),它们都有来自userService $ http调用的返回数据。但是,只有使用占位符才能使数据在视图中呈现。这是为什么? – TWLATL

+1

由于JS作用域,当你在'then'中的匿名函数中时,''this'关键字处理匿名函数,这就是为什么你需要将控制器函数实例的'this'设置为一个变量,所以该实例将在控制器内的所有“子”功能中可用。 –

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

在此位的代码this.userData实际上是被定义为一个承诺。如果你想要的是返回的数据,您需要使用d参数从.thenfunction像这样:

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

编辑 我只注意到你的服务,你已经在你的回应使用.data目的。

老实说,我给你最好的建议是只从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; 
); 

这可能是一个解决办法

+0

好的,这就是我原来的代码结构,但是通过这种方式设置,this.userData在记录时返回为undefined。这里的例子:http://plnkr.co/edit/ejHReaAIvVzlSExL5Elw?p=preview – TWLATL

+0

我刚刚更新了我的答案,以不同的结构,可能会帮助你 – CraigR8806

+0

我只是看着你的运动员。 ''this.userData'永远不会在'console.log()'出来的地方被定义。这是因为当'console.log'运行时,它仍然在等待来自web服务器的响应。如果你在你的''console.log(this.userData)'中添加''this.userData'是定义的。然后在它被设置为d后的''function' – CraigR8806