5、Angular中的$timeOut定時器

TZQ_DO_Dreamer發表於2015-03-23

  人們似乎常常將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

相關文章