如何 运行 一次事件中的函数?

How to run a function inside a event once?

我在 Angular.js 中有一个函数可以确定用户是处于非活动状态还是活动状态。当用户处于活动状态时,我想在一定时间后执行一个功能。

我有它的工作,但该函数目前 运行ning 与执行事件的数量相同。 如何保证这个函数每次执行一次?

.run(function($timeout, $document) {
    // console.log('starting run');

    // Timeout timer value
    var TimeOutTimerValue = 120000;

    // Start a timeout
    var TimeOutThread = $timeout(function() {
        LogoutByTimer();
    }, TimeOutTimerValue);
    var bodyElement = angular.element($document);

    angular.forEach(
        [
            'keydown',
            'keyup',
            'click',
            'mousemove',
            'DOMMouseScroll',
            'mousewheel',
            'mousedown',
            'touchstart',
            'touchmove',
            'scroll',
            'focus'
        ],
        function(EventName) {
            bodyElement.bind(EventName, function(e) {
                TimeOutResetter(e);
            });
        }
    );

    function LogoutByTimer() {
        console.log('Logout');
    }

    function TimeOutResetter(e) {
        console.log(' ' + e);

        $timeout(function() {
            console.log('run this once ');
        }, 2000);

        // Stop the pending timeout
        $timeout.cancel(TimeOutThread);

        // Reset the timeout
        TimeOutThread = $timeout(function() {
            LogoutByTimer();
        }, TimeOutTimerValue);
    }
})

关于函数TimeOutResetter(e)中的console.log('run this once')。 如何运行那一次?

Click here to see it on Plunker

我用你的笨蛋试过了,看我的例子:

<!DOCTYPE html>
<html ng-app="Application_TimeOut">
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.min.js"></script>
</head>

<body>
</body>

<script>
var app = angular.module('Application_TimeOut', []);
app.run(function($rootScope, $timeout, $document) {    
    console.log('starting run');
    var runOnce = true;
    // Timeout timer value
    var TimeOutTimerValue = 5000;

    // Start a timeout
    var TimeOut_Thread = $timeout(function(){ LogoutByTimer() } , TimeOutTimerValue);
    var bodyElement = angular.element($document);
    
    angular.forEach(['keydown', 'keyup', 'click', 'mousemove', 'DOMMouseScroll', 'mousewheel', 'mousedown', 'touchstart', 'touchmove', 'scroll', 'focus'], 
    function(EventName) {
         bodyElement.bind(EventName, function (e) { TimeOut_Resetter(e) });  
    });

    function LogoutByTimer(){
        console.log('Logout');
        ///////////////////////////////////////////////////
        /// redirect to another page(eg. Login.html) here
        ///////////////////////////////////////////////////
    }

    function TimeOut_Resetter(e){
        console.log(' ' + e);
        if(runOnce){
            runOnce = false;
            $timeout(function() {
                console.log('run this once');               
            }, 2000);            
        }
        
        /// Stop the pending timeout
        $timeout.cancel(TimeOut_Thread);

        /// Reset the timeout
        TimeOut_Thread = $timeout(function(){ LogoutByTimer() } , TimeOutTimerValue);
    }

})
</script>
</html>

我在顶部添加 var runOnce = true;,然后在 运行 之前添加您的命令,并在 运行ned 时更改它。

我会添加一个带有超时句柄的变量到外部范围。然后当你要开始超时时,你检查这个句柄是否被定义。如果不是,它会到达 运行.

这是一个例子:

app.run(function($rootScope, $timeout, $document) {    
    console.log('starting run');

    // Declare the handle
    var executeOnceTimeout;

    ...

    function TimeOut_Resetter(e){
        console.log(' ' + e);

        // Check if handle exists, if not continue.
        if (!executeOnceTimeout) {
            // Assign timeout-function to variable. 
            executeOnceTimeout = $timeout(function() {
                console.log('call this once');
            }, 2000);
        }
        ...
    }

})

更新

根据评论,听起来您正在寻找的是要限制一段时间的“callOnce”函数,实际上意味着它只能每 X 毫秒调用一次。

可以通过对上述代码进行以下更改来实现:

// Check if handle exists, if not continue.
if (!executeOnceTimeout) {
    // Assign timeout-function to variable. 
    executeOnceTimeout = $timeout(function() {
        // Do work
        console.log('call this once');
        // Reset callback, to enable it to be called again next time an event happens. 
        executeOnceTimeout = null;
    }, 2000);
}

You can see it in action using this Plunker.