当控制器变为后台(或无效)时需要停止正在进行的操作
Need to stop ongoing operation when controller becomes background (or invalid)
我正在编写我的第一个 AngularJS 应用程序。着陆页有两个 links #/view1
和 #/view2
。每个 link 都会调用单独的控制器来单独渲染 <div ng-view></div>
。
view1Ctrl
会定期从服务器获取数据。我可以看到 ajax 每 X 秒在控制台中调用一次。现在我点击 #/view2
,应用程序应该使用 view2Ctrl
。我预计 view1Ctrl
不应再从服务器获取数据。但实际上确实如此。
.controller('View1Ctrl', function($scope, $http) {
$scope.update = function() {
$http.get('/api/foo')
.success(function(data) { /* got new data */ })
.error(function(data) { /* error occurred */ })
.finally(function() {
setTimeout($scope.update, 1000);
});
}
$scope.update();
});
我有两个问题:
- 控制器在初始化后是否始终处于活动状态。
- 停止任何后台控制器的最佳做法是什么?我的想法是检查
$location.path()
.
更新 1:
控制器真的被销毁了。但是操作 update
会自己调用它,所以操作会被调用到无穷无尽。
我当前的解决方法是检查当前位置是否已更改。所以它有效。我正在寻找一种更优雅的方式,如果它存在的话。
.controller('View1Ctrl', function($scope, $http) {
$scope.update = function(path) {
$http.get('/api/foo')
.success(function(data) { /* got new data */ })
.error(function(data) { /* error occurred */ })
.finally(function() {
if (path === $location.path()) {
setTimeout($scope.update, 1000, path);
}
});
}
$scope.update($location.path());
});
更新二:
更好的方法是观察销毁并取消正在进行的超时承诺。谢谢@pankajparkar
.controller('View1Ctrl', function($scope, $http, $timeout) {
var timeoutPromise;
$scope.$on("$destroy", function(){
$timeout.cancel(timeoutPromise);
});
$scope.update = function() {
$http.get('/api/foo')
.success(function(data) { /* got new data */ })
.error(function(data) { /* error occurred */ })
.finally(function() {
timeoutPromise = $timeout($scope.update, 1000);
});
}
$scope.update();
});
我想你在 body 标签或你的 ng-view
的父标签上提到了 ng-controller,在你的情况下你应该从你的 $routeProvider
加载控制器来处理它,
配置
app.config(function($routeProvider) {
$routeProvider
.when('/view1', {
templateUrl: 'view1.html',
controller: 'view1Ctrl' //load specific controller from here
})
.when('/view2', {
templateUrl: 'view2.html',
controller: 'view2Ctrl' //load specific controller from here
})
.otherwise({
redirectTo: '/view1'
});
});
HTML
<div class="wizard">
<ng-view></ng-view>
</div>
以下是您问题的答案。
- 现在,当
$routeProvider
加载 view1.html
时,view1Ctrl
将存在,一旦用户导航到 view2.html
,view1Ctrl
将停止工作 view2Ctrl
将出现在你提到的路线配置中。
- 您应该始终使用
$routeProvider
或 $stateProvider
(angular-ui-router) 在您的应用程序中设置路由,并在基础上加载 templates
和 controller
路由。不用勾选 $location.path()
更新
您的问题出在重复的函数调用上,即使在控制器作用域从 DOM 中消失后,它仍然在后台 运行。
在重定向到其他控制器时清除此功能的最佳方法。
我建议你把你的 $timeout
承诺(你使用 setTimeout
将它更改为 $timeout
)在一个 java 脚本变量中,并在离开时取消它(注销控制器) ).离开控制器时 $destroy
事件由 angular 调度,这类似于控制器的 destruct-or
,您可以使用它,您可以取消其中的 $timeout
承诺。
代码
var timeoutPromise = setTimeout($scope.update, 1000);
$scope.$on("$destroy", function(){
$timeout.cancel(timeoutPromise);
});
Plunkr 取消了 $timeout
的承诺。
Reference Link
希望对您有所帮助,谢谢。
我正在编写我的第一个 AngularJS 应用程序。着陆页有两个 links #/view1
和 #/view2
。每个 link 都会调用单独的控制器来单独渲染 <div ng-view></div>
。
view1Ctrl
会定期从服务器获取数据。我可以看到 ajax 每 X 秒在控制台中调用一次。现在我点击 #/view2
,应用程序应该使用 view2Ctrl
。我预计 view1Ctrl
不应再从服务器获取数据。但实际上确实如此。
.controller('View1Ctrl', function($scope, $http) {
$scope.update = function() {
$http.get('/api/foo')
.success(function(data) { /* got new data */ })
.error(function(data) { /* error occurred */ })
.finally(function() {
setTimeout($scope.update, 1000);
});
}
$scope.update();
});
我有两个问题:
- 控制器在初始化后是否始终处于活动状态。
- 停止任何后台控制器的最佳做法是什么?我的想法是检查
$location.path()
.
更新 1:
控制器真的被销毁了。但是操作 update
会自己调用它,所以操作会被调用到无穷无尽。
我当前的解决方法是检查当前位置是否已更改。所以它有效。我正在寻找一种更优雅的方式,如果它存在的话。
.controller('View1Ctrl', function($scope, $http) {
$scope.update = function(path) {
$http.get('/api/foo')
.success(function(data) { /* got new data */ })
.error(function(data) { /* error occurred */ })
.finally(function() {
if (path === $location.path()) {
setTimeout($scope.update, 1000, path);
}
});
}
$scope.update($location.path());
});
更新二:
更好的方法是观察销毁并取消正在进行的超时承诺。谢谢@pankajparkar
.controller('View1Ctrl', function($scope, $http, $timeout) {
var timeoutPromise;
$scope.$on("$destroy", function(){
$timeout.cancel(timeoutPromise);
});
$scope.update = function() {
$http.get('/api/foo')
.success(function(data) { /* got new data */ })
.error(function(data) { /* error occurred */ })
.finally(function() {
timeoutPromise = $timeout($scope.update, 1000);
});
}
$scope.update();
});
我想你在 body 标签或你的 ng-view
的父标签上提到了 ng-controller,在你的情况下你应该从你的 $routeProvider
加载控制器来处理它,
配置
app.config(function($routeProvider) {
$routeProvider
.when('/view1', {
templateUrl: 'view1.html',
controller: 'view1Ctrl' //load specific controller from here
})
.when('/view2', {
templateUrl: 'view2.html',
controller: 'view2Ctrl' //load specific controller from here
})
.otherwise({
redirectTo: '/view1'
});
});
HTML
<div class="wizard">
<ng-view></ng-view>
</div>
以下是您问题的答案。
- 现在,当
$routeProvider
加载view1.html
时,view1Ctrl
将存在,一旦用户导航到view2.html
,view1Ctrl
将停止工作view2Ctrl
将出现在你提到的路线配置中。 - 您应该始终使用
$routeProvider
或$stateProvider
(angular-ui-router) 在您的应用程序中设置路由,并在基础上加载templates
和controller
路由。不用勾选$location.path()
更新
您的问题出在重复的函数调用上,即使在控制器作用域从 DOM 中消失后,它仍然在后台 运行。
在重定向到其他控制器时清除此功能的最佳方法。
我建议你把你的 $timeout
承诺(你使用 setTimeout
将它更改为 $timeout
)在一个 java 脚本变量中,并在离开时取消它(注销控制器) ).离开控制器时 $destroy
事件由 angular 调度,这类似于控制器的 destruct-or
,您可以使用它,您可以取消其中的 $timeout
承诺。
代码
var timeoutPromise = setTimeout($scope.update, 1000);
$scope.$on("$destroy", function(){
$timeout.cancel(timeoutPromise);
});
Plunkr 取消了 $timeout
的承诺。
Reference Link
希望对您有所帮助,谢谢。