clearTimeout 不清除超时变量
clearTimeout doesn't clear the timeout variable
我有一个应用程序需要在 28 分钟后超时。它将显示 jQuery 对话框 2 分钟。如果用户在两分钟内单击 "Ok",计时器将刷新为 28 分钟,当倒计时达到 0 分钟时,它应该再次显示 jQuery 对话框。
问题是当我调试时,我看到超时变量没有清除超时。单击 "Ok" 后,计时器重置为 28 分钟,但当倒计时达到 0 分钟时,setTimeout 不会再次显示对话框。
这是我的代码:
var timeout;
function timer() {
countDownDate = 0;
console.log("Hello");
countDownDate = 0;
var timeExpires = new Date().getTime();
countDownDate = timeExpires + 1680000;
now = 0;
distance = 0;
if(timeout){
clearTimeout(timeout);
}
// Update the count down every 1 second
var x = setInterval(function () {
// Get todays date and time
now = new Date().getTime();
// Find the distance between now an the count down date
distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
if (distance < 0) {
if ($("#alert").length) {
var title;
if ($("#alert span").length) {
title = $("#alert span").text();
}
$("#alert div").dialog({
title: title,
modal: true,
buttons: {
Ok: function() {
var foo = $(this);
clearTimeout(timeout);
timer();
foo.dialog('close');
},
Cancel: function() {
esriId.destroyCredentials();
window.location.replace(redirect_uri);
}
}/*,
open: function() {
var foo = $(this);
timeout = setTimeout(function() {
foo.dialog('close');
esriId.destroyCredentials();
window.location.replace(redirect_uri);
}, 120000);
},*/
});
}
timeout = setTimeout($("#alert div").dialog("open"), 120000);
clearInterval(x);
}
}, 1000);
};
这是警报的 HTML div:
<div id="alert" style="display:none">
<span>You will be signed out</span>
<div>You will be signed out due to inactivity on the page. If you wish to stay on the page, please press 'Ok'</div>
</div>
例如:
function open() {
$("#alert div").dialog("open");
}
timeout = setTimeout(open, 120000);
事情是,一旦你实例化一个 .dialog()
,它使用 span
和 div
。
所以你必须刷新那些。
我让它在这个 CodePen 中工作。 (我为了测试缩短了时间)
在timer()
函数之前,添加:
var alertHTML = $("#alert").html();
那么,在函数中,技巧就在这里:
var title;
if ($("#alert div").length) {
console.log("alert is present");
}else{
console.log("alert is missing");
$("#alert").html(alertHTML);
}
title = $("#alert span").text();
如所写,
setTimeout()
命令构造错误。
- 您似乎想在 28 分钟到期时打开对话框,如果未单击“确定”,则在 2 分钟后自动关闭它;但是您正在使用那个 2 分钟计时器来 打开 对话框,而不是 关闭 它。
- 里面只见树木不见林
timer()
。
timer()
可以简化为:
- 在
timer()
之外的函数中定义对话框设置。
- 在
timer()
之外的函数中定义倒计时器 calcs/display。
- 引入第三个计时器来管理 28 分钟的持续时间 - 这避免了在时间显示功能中测试
if (distance < 0)
等的需要。
这是修改后的代码:
// set up the dialog
function showDialog(callback) {
$("#alert div").dialog('destroy').dialog({
title: $("#alert span").length ? $("#alert span").text() : '---',
modal: true,
buttons: {
Ok: function() {
$(this).dialog('close');
callback('ok')
},
Cancel: function() {
// $(this).dialog('close'); // ?
callback('cancel');
}
}
}).dialog('open');
}
// function for calculating and displayig the countdown values
function displayCountdown(t) {
var distance = Math.max(0, t - Date.now());
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// ... display days, hours, minutes, seconds somewhere
}
// object which defines the three timers
var timers = {
'ticker': { 'ref': null, 't': 1000 }, // 1 second
'stopTicker': { 'ref': null, 't': 1680000}, // 28 minutes
'cancelDialog': { 'ref': null, 't': 120000 } // 2 minutes
}
function redirect() {
esriId.destroyCredentials();
window.location.replace(redirect_uri);
}
//
function timer() {
clearInterval(timers.ticker.ref);
clearTimeout(timers.stopTicker.ref);
clearTimeout(timers.cancelDialog.ref);
timers.stopTicker.ref = setTimeout(function() {
clearInterval(timers.ticker.ref);
showDialog(function(outcome) {
if(outcome === 'ok') {
timer();
} else {
redirect();
}
});
timers.cancelDialog.ref = setTimeout(redirect, timers.cancelDialog.t);
}, timers.stopTicker.t);
timers.ticker.ref = setInterval(displayCountdown.bind(null, Date.now() + timers.stopTicker.t), timers.ticker.t);
};
请注意,redirect()
将以两种可能的方式调用:
- 响应对话被取消。
- 响应 2 分钟到期。
传递给 showDialog()
的回调并非绝对必要,但允许对话完全不知道其结果的后果。所有这些逻辑都在调用者中,timer()
.
另一种可以说更简洁的方法是承诺对话。
这里,除showDialog()
和timer()
外,其他都和上面一样。
// set up a promisified dialog
function showDialog() {
return $.Deferred(function(dfrd) {
$("#alert div").dialog('destroy').dialog({
'title': $("#alert span").length ? $("#alert span").text() : '---',
'modal': true,
'buttons': {
'Ok': dfrd.resolve, // yay!
'Cancel': dfrd.reject // yay!
}
}).dialog('open');
}).always(function() {
$("#alert div").dialog('close');
});
}
function timer() {
clearTimeout(timers.ticker.ref);
clearTimeout(timers.stopTicker.ref);
clearTimeout(timers.cancelDialog.ref);
timers.stopTicker.ref = setTimeout(function() {
clearInterval(timers.ticker.ref);
$.Deferred(function(dfrd) { // "race" pattern
showDialog().then(dfrd.resolve, dfrd.reject);
timers.cancelDialog.ref = setTimeout(dfrd.reject, timers.cancelDialog.t);
}).then(timer, redirect); // yay-yay!
}, timers.stopTicker.t);
timers.ticker.ref = setInterval(displayCountdown.bind(null, Date.now() + timers.stopTicker.t), timers.ticker.t);
};
我有一个应用程序需要在 28 分钟后超时。它将显示 jQuery 对话框 2 分钟。如果用户在两分钟内单击 "Ok",计时器将刷新为 28 分钟,当倒计时达到 0 分钟时,它应该再次显示 jQuery 对话框。
问题是当我调试时,我看到超时变量没有清除超时。单击 "Ok" 后,计时器重置为 28 分钟,但当倒计时达到 0 分钟时,setTimeout 不会再次显示对话框。
这是我的代码:
var timeout;
function timer() {
countDownDate = 0;
console.log("Hello");
countDownDate = 0;
var timeExpires = new Date().getTime();
countDownDate = timeExpires + 1680000;
now = 0;
distance = 0;
if(timeout){
clearTimeout(timeout);
}
// Update the count down every 1 second
var x = setInterval(function () {
// Get todays date and time
now = new Date().getTime();
// Find the distance between now an the count down date
distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
if (distance < 0) {
if ($("#alert").length) {
var title;
if ($("#alert span").length) {
title = $("#alert span").text();
}
$("#alert div").dialog({
title: title,
modal: true,
buttons: {
Ok: function() {
var foo = $(this);
clearTimeout(timeout);
timer();
foo.dialog('close');
},
Cancel: function() {
esriId.destroyCredentials();
window.location.replace(redirect_uri);
}
}/*,
open: function() {
var foo = $(this);
timeout = setTimeout(function() {
foo.dialog('close');
esriId.destroyCredentials();
window.location.replace(redirect_uri);
}, 120000);
},*/
});
}
timeout = setTimeout($("#alert div").dialog("open"), 120000);
clearInterval(x);
}
}, 1000);
};
这是警报的 HTML div:
<div id="alert" style="display:none">
<span>You will be signed out</span>
<div>You will be signed out due to inactivity on the page. If you wish to stay on the page, please press 'Ok'</div>
</div>
例如:
function open() {
$("#alert div").dialog("open");
}
timeout = setTimeout(open, 120000);
事情是,一旦你实例化一个 .dialog()
,它使用 span
和 div
。
所以你必须刷新那些。
我让它在这个 CodePen 中工作。 (我为了测试缩短了时间)
在timer()
函数之前,添加:
var alertHTML = $("#alert").html();
那么,在函数中,技巧就在这里:
var title;
if ($("#alert div").length) {
console.log("alert is present");
}else{
console.log("alert is missing");
$("#alert").html(alertHTML);
}
title = $("#alert span").text();
如所写,
setTimeout()
命令构造错误。- 您似乎想在 28 分钟到期时打开对话框,如果未单击“确定”,则在 2 分钟后自动关闭它;但是您正在使用那个 2 分钟计时器来 打开 对话框,而不是 关闭 它。
- 里面只见树木不见林
timer()
。
timer()
可以简化为:
- 在
timer()
之外的函数中定义对话框设置。 - 在
timer()
之外的函数中定义倒计时器 calcs/display。 - 引入第三个计时器来管理 28 分钟的持续时间 - 这避免了在时间显示功能中测试
if (distance < 0)
等的需要。
这是修改后的代码:
// set up the dialog
function showDialog(callback) {
$("#alert div").dialog('destroy').dialog({
title: $("#alert span").length ? $("#alert span").text() : '---',
modal: true,
buttons: {
Ok: function() {
$(this).dialog('close');
callback('ok')
},
Cancel: function() {
// $(this).dialog('close'); // ?
callback('cancel');
}
}
}).dialog('open');
}
// function for calculating and displayig the countdown values
function displayCountdown(t) {
var distance = Math.max(0, t - Date.now());
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// ... display days, hours, minutes, seconds somewhere
}
// object which defines the three timers
var timers = {
'ticker': { 'ref': null, 't': 1000 }, // 1 second
'stopTicker': { 'ref': null, 't': 1680000}, // 28 minutes
'cancelDialog': { 'ref': null, 't': 120000 } // 2 minutes
}
function redirect() {
esriId.destroyCredentials();
window.location.replace(redirect_uri);
}
//
function timer() {
clearInterval(timers.ticker.ref);
clearTimeout(timers.stopTicker.ref);
clearTimeout(timers.cancelDialog.ref);
timers.stopTicker.ref = setTimeout(function() {
clearInterval(timers.ticker.ref);
showDialog(function(outcome) {
if(outcome === 'ok') {
timer();
} else {
redirect();
}
});
timers.cancelDialog.ref = setTimeout(redirect, timers.cancelDialog.t);
}, timers.stopTicker.t);
timers.ticker.ref = setInterval(displayCountdown.bind(null, Date.now() + timers.stopTicker.t), timers.ticker.t);
};
请注意,redirect()
将以两种可能的方式调用:
- 响应对话被取消。
- 响应 2 分钟到期。
传递给 showDialog()
的回调并非绝对必要,但允许对话完全不知道其结果的后果。所有这些逻辑都在调用者中,timer()
.
另一种可以说更简洁的方法是承诺对话。
这里,除showDialog()
和timer()
外,其他都和上面一样。
// set up a promisified dialog
function showDialog() {
return $.Deferred(function(dfrd) {
$("#alert div").dialog('destroy').dialog({
'title': $("#alert span").length ? $("#alert span").text() : '---',
'modal': true,
'buttons': {
'Ok': dfrd.resolve, // yay!
'Cancel': dfrd.reject // yay!
}
}).dialog('open');
}).always(function() {
$("#alert div").dialog('close');
});
}
function timer() {
clearTimeout(timers.ticker.ref);
clearTimeout(timers.stopTicker.ref);
clearTimeout(timers.cancelDialog.ref);
timers.stopTicker.ref = setTimeout(function() {
clearInterval(timers.ticker.ref);
$.Deferred(function(dfrd) { // "race" pattern
showDialog().then(dfrd.resolve, dfrd.reject);
timers.cancelDialog.ref = setTimeout(dfrd.reject, timers.cancelDialog.t);
}).then(timer, redirect); // yay-yay!
}, timers.stopTicker.t);
timers.ticker.ref = setInterval(displayCountdown.bind(null, Date.now() + timers.stopTicker.t), timers.ticker.t);
};