javascript AngularJs $scope 在对工厂发出 GET 请求后不会更新
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21854296/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AngularJs $scope doesn't update after a GET request on a factory
提问by Jo?o Martins
I have been trying AngularJS for a experimental project and I came along with this problem. In my html I want to display a list of items
我一直在为一个实验项目尝试 AngularJS,但我遇到了这个问题。在我的 html 中,我想显示一个项目列表
Index.html
索引.html
<h1>Some list</h1>
<div ng-controller="datlist">
<div ng-repeat="item in items">
<div>Item description: {{item.description}}</div>
<div>Item name: {{item.name}}</div>
</div>
</div>
At first I was using a simple controller to get the information and update the view just using this:
起初我使用一个简单的控制器来获取信息并使用这个更新视图:
controllers.js (original)
控制器.js(原始)
function datlist($scope,$http){
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}).
success(function(data, status, headers, config) {
$scope.items=data.itemsToReturn;
console.log(data);
}).
error(function(data, status, headers, config) {
console.log("fail");
});
}
This was working pretty well and I could get the list of items. Whilst, by changing my structure to use a factory to make the same request and bind it to $scope.items it doesn't work. I tried a lot of variations of $watch but I couldn't get it to update $scope.items. I found something about $apply but I really can't understand how to use it.
这工作得很好,我可以获得项目列表。同时,通过更改我的结构以使用工厂来发出相同的请求并将其绑定到 $scope.items 它不起作用。我尝试了很多 $watch 的变体,但我无法让它更新 $scope.items。我发现了一些关于 $apply 的东西,但我真的不明白如何使用它。
controllers.js (new one)
controller.js(新的)
var datModule = angular.module('datModule',[]);
datModule.controller('datlist', function ($scope, datfactory){
$scope.items = datfactory.getlist();
$scope.$watch($scope.items, $scope.items = datfactory.getlist());
});
datModule.factory('datfactory', function ($http){
var factory = {};
factory.getlist = function(){
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}).
success(function(data, status, headers, config) {
console.log(data.itemsToReturn); //I get the correct items, all seems ok here
return data.itemsToReturn;
}).
error(function(data, status, headers, config) {
console.log("fail");
});
}
return factory;
});
Any ideas about this will be great. PS: I found a lot of posts talking about this issue but none of them helped me to get a full solution.
关于这个的任何想法都会很棒。PS:我发现很多帖子都在讨论这个问题,但没有一个能帮助我找到完整的解决方案。
Thanks
谢谢
回答by Konstantin Krass
Using a watch for that is kinda ugly.
为此使用手表有点丑陋。
try this:
试试这个:
datModule.factory('datfactory', function ($http, $q){
this.getlist = function(){
return $http.get('http://localhost:61686/getdatlist?format=json',{'Access-Control-Allow-Origin': 'localhost:*'})
.then(function(response) {
console.log(response); //I get the correct items, all seems ok here
return response.data.itemsToReturn;
});
}
return this;
});
datModule.controller('datlist', function ($scope, datfactory){
datfactory.getlist()
.then(function(arrItems){
$scope.items = arrItems;
});
});
This is how you use promises for async matter.
这就是你如何使用 Promise 来处理异步事务。
UPDATE (15.01.2015): Now even sleeker!
更新 (15.01.2015):现在更时尚!
回答by Dan Saltmer
The issue is nothing to do with the scope digest cycle. You are trying to return from inside a callback directly, which is not asynchronously possible.
该问题与范围摘要周期无关。您试图直接从回调内部返回,这是不可能异步的。
I recommend you either use a promise, or return the http promise directly.
我建议您要么使用承诺,要么直接返回 http 承诺。
var factory = {};
factory.getlist = function(){
return $http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}});
}
return factory;
To return the promise directly, and handle the success/fail at factory.getlist().success()
直接返回承诺,并处理成功/失败 factory.getlist().success()
Alternatively, use your own promise if you want to wrap additional logic around the request.
或者,如果您想围绕请求包装额外的逻辑,请使用您自己的承诺。
var datModule = angular.module('datModule',[]);
datModule.controller('datlist', function ($scope, datfactory){
$scope.items = [];
datfactory.getlist().then(function(data) { $scope.items = data });
});
datModule.factory('datfactory', function ($http, $q){
var factory = {};
factory.getlist = function(){
var defer = $q.defer();
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}).
success(function(data) {
// alter data if needed
defer.resolve(data.itemsToReturn);
}).
error(function(data, status, headers, config) {
defer.reject();
});
return defer.promise;
}
return factory;
});
回答by Jay Shukla
Well it looks perfect but you can use $apply
like this.
好吧,它看起来很完美,但您可以$apply
像这样使用。
datModule.controller('datlist', function ($scope, datfactory){
$scope.$apply(function() {
$scope.items = datfactory.getlist();
});
});
回答by Jorge Guerola
try to initialize $scope.items = [];
at controller, before call $http
尝试$scope.items = [];
在控制器初始化,然后调用 $http
I hope it helps you.
我希望它能帮助你。
回答by Nandor Persanyi
I think another elegant solution to this problem could be - if you are using one of the routing libraries, in my case it is the UI-Router, but could be also ngRoute, is making your controller dependent on the response of the promise, eg. adding a resolve property to the adequate state/route which doesn't let the controller load until the promise is solved and the data is ready, so in your config:
我认为这个问题的另一个优雅的解决方案可能是 - 如果你正在使用其中一个路由库,在我的例子中它是 UI-Router,但也可能是 ngRoute,使你的控制器依赖于承诺的响应,例如. 将解析属性添加到适当的状态/路由中,在承诺解决且数据准备好之前不会让控制器加载,因此在您的配置中:
.state('datpage', {
url: '/datpage',
controller: 'DatpageController',
resolve:{
datData: function (datfactory) {
return datDataService.getData("datDataParam");
}]
},
templateUrl: 'views/datpage.html'
})
And inject the datData dependency in your controller, where you can apply it directly to the $scope:
并在您的控制器中注入 datData 依赖项,您可以在其中直接将其应用于 $scope:
.controller('DatpageController', function ($scope,datData) {
$scope.datPageData = datData; ...