在 Angular 控制器中处理异步更新的正确方法
Proper Way to Handle Asynchronous Updates in Angular Controller
这是我的设置 -- 我有一个控制器,它使用的服务可以完成一些工作,然后异步地 returns 数据。在这种情况下,数据是通过超时返回的,但在现实生活中,这会做一些更有趣的事情:
查看:
<div ng-controller="RootController as root">
<h1>Angular Project</h1>
<div ng-show="{{root.greeting}}">
<p>{{root.greeting}}</p>
</div>
</div>
控制器:
(function(){
'use strict';
function RootController(greetingService) {
var vm = this;
vm.greeting = '';
// startup logic
activate();
function activate() {
greetingService.greeting().then(
function( response ) {
vm.greeting = response;
},
function( error ) {
vm.greeting = error;
}
);
}
}
RootController.$inject = ['greeting'];
angular.module('app.core').controller('RootController', RootController);
})();
服务:
(function() {
'use strict';
// Greeting Service
function greeting( $timeout ) {
// public API
var service = {
greeting: greeting
};
return service;
// internal functions
function greeting() {
return $timeout( function() {
return 'Hello world!';
}, 1000 );
}
}
temp.$inject = ['$timeout'];
angular.module('app.core').factory( 'greeting', greeting );
})();
问题:
为什么当超时解决并且我的控制器中发生 vm.greeting 分配时我的视图没有更新?我看到有人描述"inside Angular vs outside Angular",但在我看来我没有去过"outside Angular"这里。
我知道我可以调用 $scope.$apply(),但我遇到了“digest is already in progress”错误,而且我似乎又不应该这样做。
有没有更好的方法来组织我的组件?我还尝试过通过 $rootScope 广播事件并在控制器中编写事件处理程序,但这种安排表现出相同的结果(即当异步模型更改发生时视图未更新)。
ng-show 不需要花括号
https://docs.angularjs.org/api/ng/directive/ngShow
改变
<div ng-show="{{root.greeting}}">
至
<div ng-show="root.greeting">
您构建代码的方式与我通常采用的方式大不相同。查看此 link 以获得出色的风格指南。http://toddmotto.com/opinionated-angular-js-styleguide-for-teams/
至于您的问题,Angular 使用 $scope 将控制器中的值绑定到视图。所以你的控制器应该注入 $scope 然后你可以做 $scope.greeting 代替 vm.greeting.
这是我的设置 -- 我有一个控制器,它使用的服务可以完成一些工作,然后异步地 returns 数据。在这种情况下,数据是通过超时返回的,但在现实生活中,这会做一些更有趣的事情:
查看:
<div ng-controller="RootController as root">
<h1>Angular Project</h1>
<div ng-show="{{root.greeting}}">
<p>{{root.greeting}}</p>
</div>
</div>
控制器:
(function(){
'use strict';
function RootController(greetingService) {
var vm = this;
vm.greeting = '';
// startup logic
activate();
function activate() {
greetingService.greeting().then(
function( response ) {
vm.greeting = response;
},
function( error ) {
vm.greeting = error;
}
);
}
}
RootController.$inject = ['greeting'];
angular.module('app.core').controller('RootController', RootController);
})();
服务:
(function() {
'use strict';
// Greeting Service
function greeting( $timeout ) {
// public API
var service = {
greeting: greeting
};
return service;
// internal functions
function greeting() {
return $timeout( function() {
return 'Hello world!';
}, 1000 );
}
}
temp.$inject = ['$timeout'];
angular.module('app.core').factory( 'greeting', greeting );
})();
问题:
为什么当超时解决并且我的控制器中发生 vm.greeting 分配时我的视图没有更新?我看到有人描述"inside Angular vs outside Angular",但在我看来我没有去过"outside Angular"这里。
我知道我可以调用 $scope.$apply(),但我遇到了“digest is already in progress”错误,而且我似乎又不应该这样做。
有没有更好的方法来组织我的组件?我还尝试过通过 $rootScope 广播事件并在控制器中编写事件处理程序,但这种安排表现出相同的结果(即当异步模型更改发生时视图未更新)。
ng-show 不需要花括号
https://docs.angularjs.org/api/ng/directive/ngShow
改变
<div ng-show="{{root.greeting}}">
至
<div ng-show="root.greeting">
您构建代码的方式与我通常采用的方式大不相同。查看此 link 以获得出色的风格指南。http://toddmotto.com/opinionated-angular-js-styleguide-for-teams/
至于您的问题,Angular 使用 $scope 将控制器中的值绑定到视图。所以你的控制器应该注入 $scope 然后你可以做 $scope.greeting 代替 vm.greeting.