Javascript 如何在事件中运行函数一次?
我在Angular.js中有一个函数来确定用户是非活动的还是活动的。当用户处于活动状态时,我希望在一段时间后执行一个函数 我已经让它工作了,但是函数当前正在以与已执行事件相同的数量运行。 如何确保此函数每次执行一次Javascript 如何在事件中运行函数一次?,javascript,angularjs,dom-events,Javascript,Angularjs,Dom Events,我在Angular.js中有一个函数来确定用户是非活动的还是活动的。当用户处于活动状态时,我希望在一段时间后执行一个函数 我已经让它工作了,但是函数当前正在以与已执行事件相同的数量运行。 如何确保此函数每次执行一次 .run(function($timeout, $document) { // console.log('starting run'); // Timeout timer value var TimeOutTimerValue = 120000;
.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('runthis once')
。
如何运行一次
我用你的弹跳和工作进行了尝试,请参见我的示例:
<!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 app=angular.module('应用程序超时',[]);
运行(函数($rootScope,$timeout,$document){
console.log(“开始运行”);
var runOnce=真;
//超时计时器值
var TimeOutTimerValue=5000;
//开始超时
var TimeOut_Thread=$TimeOut(函数(){LogoutByTimer()},TimeOutTimerValue);
var bodyElement=angular.element($document);
angular.forEach(['keydown'、'keyup'、'click'、'mousemove'、'DOMMouseScroll'、'mousewheel'、'mousedown'、'touchstart'、'touchmove'、'scroll'、'focus']),以及,
函数(EventName){
bind(EventName,函数(e){TimeOut\u Resetter(e)});
});
函数LogoutByTimer(){
console.log(“注销”);
///////////////////////////////////////////////////
///在此处重定向到另一个页面(如Login.html)
///////////////////////////////////////////////////
}
功能超时\u重置器(e){
控制台日志(“”+e);
如果(跳动){
跳动=假;
$timeout(函数(){
log('运行一次');
}, 2000);
}
///停止挂起的超时
$timeout.cancel(超时线程);
///重置超时
TimeOut_Thread=$TimeOut(函数(){LogoutByTimer()},TimeOutTimerValue);
}
})
我添加
var runOnce=true代码>在顶部,然后在运行命令之前添加if,并在命令运行时更改它。我会在外部范围中添加一个带有超时句柄的变量。然后,当您即将开始超时时,检查是否定义了此句柄。如果没有,它就会运行
下面是一个例子:
app.run(函数($rootScope,$timeout,$document){
console.log(“开始运行”);
//声明句柄
var executeOnceTimeout;
...
功能超时\u重置器(e){
控制台日志(“”+e);
//检查句柄是否存在,如果不存在,请继续。
如果(!executeOnceTimeout){
//将超时函数分配给变量。
executeOnceTimeout=$timeout(函数(){
log('callthis 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);
}
我认为最简单的方法是创建一个值为false的全局变量,然后为要运行1次的部件创建一个if,看看是否为false并运行它,运行时将var更改为true,以便下次与条件不匹配是的,看起来不错,让我试试。@SimoneRossaini否不起作用,像var runOnce=false一样尝试$超时(函数(){if(!runOnce){console.log('send session');}runOnce=true;},2000)代码>如果您希望在源代码中为多个函数实现相同的行为(仅运行一次),您可能希望将该行为抽象为包装函数,使您能够动态地“onceify”任何函数,如myfunctionone=once(myFunction)
。请参阅:。这将执行控制台日志一次,但需要在事件再次发生时再次执行。现在它只执行一次,但每次事件后都需要重复。您希望它在什么时候重置?只要在需要重置时重新分配变量executeOnceTimeout=null
,下次调用TimeOut\u reseter
-函数时,它就会再次运行。我想做的是,当您拥有47[object MouseEvent]
时,会显示一次带有日志的函数,在此之后,您将有另一个事件17[object MouseEvent]
,在此事件之后,我想再次显示日志,因此在每个事件之后,都会显示日志/函数。您可以将executeOnceTimeout=null
添加到callOnce函数的末尾。这样做的目的是,每次callOnce函数完成时,它都会重置。实际上,这意味着callOnce函数最多每2000ms调用一次。这种效应称为节流。这就是你想要的吗?不客气。我已经更新了答案以更好地反映您的意图。这将执行控制台日志一次,但需要在事件再次发生时再次执行。现在它只做一次,当事件再次发生时它会停止再做一次,但每次事件发生后它都需要重复一次。很简单,注销时添加true。