clearTimeout不清除超时变量

时间:2017-07-10 02:18:43

标签: javascript jquery dialog settimeout cleartimeout

我有一个需要在28分钟后超时的应用程序。它将显示jQuery对话框2分钟。如果用户点击"确定"在两分钟内,计时器刷新到28分钟,当倒计时达到0分钟时,它应该再次显示jQuery对话框。

问题是当我调试时,我看到超时变量没有清除超时。单击"确定"后,计时器重置为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>

3 个答案:

答案 0 :(得分:0)

例如:

function open() {
  $("#alert div").dialog("open");
 }

 timeout = setTimeout(open, 120000);

答案 1 :(得分:0)

问题在于,一旦您实例化span,就会使用divtimer()

所以你必须刷新那些 我在这个CodePen中工作了。 (我缩短了测试时间)

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();

然后,在函数中,技巧就在这里:

Subject

答案 2 :(得分:0)

正如所写,

  • setTimeout()命令构造错误。
  • 您似乎想在28分钟到期时打开对话框,如果没有点击确定,则在2分钟后自动关闭对话框;但你使用那个2分钟的计时器打开对话框,而不是关闭它。
  • 很难看到timer()内的树木。

timer()可以简化为:

  • timer()之外的函数中定义对话框设置。
  • 定义倒数计时器计算/显示在timer()之外的函数中。
  • 引入第三个计时器来管理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()将以两种可能的方式调用:

  1. 响应对话框被取消。
  2. 响应2分钟的到期。
  3. 传递给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);
    };