人们似乎常常将AngularJS中的$timeOut()函数看做是一个内置的、无须在意的函数。但是,如果你忘记了$timeOut()的回调函数将会造成非常不好的影响,你可能会因此遇到代码莫名其妙的出现问题,或者无端抛出一个错误甚至是一遍一遍的重复对的你的服务器进行$http请求这些诡异的情形。管理好你的$timeOut定时器的小技巧就是在$destory事件中将它们取消。
和javascript中原生的setTimeout()以及setInterval()函数不同,AngularJS中的$timeOut()函数会返回一个promise。和其他的promise一样,你可以绑定$timeOut的resolved和rejected时间。然而更重要的是,你可以通过将这个promise传递给$timeOut.cancel()方法来取消掉潜在的定时器。
在一个AngularJS应用中,这一点非常的重要,因为定时器可以结束执行那些不再与应用状态和用户界面相关的代码。最佳情形中,这些过程都会悄悄的发生;在不好的情况下,它会引起不可预测的行为并导致很差的用户体验。为了让应用顺畅的运行,你应该总是把握好你的$timeOut定时器;你需要在相应的控制器和指令接收到$destory事件时调用$timeOut.cancel()方法。
为了更加清楚的说明这点,下面的这个例子将会有一些DOM元素通过ngSwitch/ngSwitchWhen指令来创建或销毁。注意到当$destory事件被触发时(在这里的例子中是位于指令中),我们将取消当前的定时器:
/* * $timeout定时器测试 */ // 定义控制器 test.controller( "DemoController", function( $scope ) { $scope.section = "htesty"; //在toggle函数中改变section的值,以此在标记中显示/隐藏不同的部分 $scope.toggle = function() { if ( $scope.section === "htesty" ) { $scope.section = "sad"; } else { $scope.section = "htesty"; } }; } ); //定义指令 test.directive("bnDirective", function($timeout) { //将用户界面的事件绑定到$scope上 function link($scope, element, attributes) { //当timeout被定义时,它返回一个promise对象 var timer = $timeout(function() { console.log("Timeout executed", Date.now()); }, 3000); //将resolve/reject处理函数绑定到timer promise上以确保我们的cancel方法能正常运行 timer.then(function() { console.log("Timer resolved!", Date.now()); }, function() { console.log("Timer rejected!", Date.now()); }); //★当DOM元素从页面中被移除时,AngularJS将会在scope中触发$destory事件。这让我们可以有机会来cancel任何潜在的定时器 $scope.$on("$destroy", function(event) { $timeout.cancel(timer); console.log("timer has been removed!"); }); } //返回指令的配置 return ({ link : link, scope : false }); });
<div ng-controller="DemoController"> <h4>Don't Forget To Cancel $timeout Timers In Your $destroy Events In AngularJS</h4> <p> <a href="#" ng-click="toggle()">Toggle Section</a> </p> <div ng-switch="section"> <p ng-switch-when="happy" bn-directive>Oh sweet!</p> <p ng-switch-when="sad" bn-directive >Oh noes!</p> </div> </div>
"Timeout executed" 1427091576150
"Timer resolved!" 1427091576151
"timer has been removed!"
本文译自Don’t Forget To Cancel $timeout Timers In Your $destroy Events In AngularJS,
原文地址为http://www.bennadel.com/blog/2548-Don-t-Forget-To-Cancel-timeout-Timers-In-Your-destroy-Events-In-AngularJS.htm