Javascript:经过一段时间后执行操作

时间:2013-10-10 13:28:53

标签: javascript jquery

我有一个页面,用于触发ajax请求,并在用户按下按钮后的前6秒显示加载符号:

<button onclick="runLoader();"></button>

<script>
    var startTime=(new Date).getTime();
    function runLoader(){
        runAjax();
        var i=0;
        var timer = setInterval(function(e){
            i++;
            //code for loading sign
            if(i==3)
                clearInterval(timer);
        } ,2000);
    }

    function runAjax(){
        $.ajax({
            //
        }).done(function(){
            var timer2 = setInterval(function(){
                var d = new Date();
                var t = d.getTime();
                if(t-startTime>=6000){
                    clearInterval(timer2);
                    // do X
                }
            },500);
        }
    }
</script>

我希望仅在runLoader()运行6秒且runAjax()导致响应后立即采取行动 X

就像,如果runAjax()在2秒内响应,我仍然希望继续显示加载符号6秒,然后执行 X 。 如果加载符号显示6秒,我想等待runAjax()返回,只要它需要。

但使用Date()方法会产生不准确的结果。例如:即使仅过了2秒,它也会显示7.765秒。我在某个地方阅读console.log(time)以获得更高的准确性,但它在&lt; = IE9中无效。

有没有更好的方法来解决这个问题?

注意:我使用的是setInterval()而不是setTimeout(),因为加载涉及循环播放3个元素的数组,“提取”,“处理”和“加载”每个显示2秒:)

3 个答案:

答案 0 :(得分:8)

我会使用deferreds$.when

function start(){
    $.when(runLoader(), runAjax()).done(function() {
        //both are now finished
    });
}

function runLoader() {
    //show loader here

    var def = $.Deferred();

    setTimeout(function() {
        //hide loader here
        def.resolve(true);
    }, 6000);

    return def.promise();
}

function runAjax() {
    var def = $.Deferred();

    $.ajax({...}).done(function(result) {
        //handle response here
        def.resolve(true);
    });

    return def.promise();
}

答案 1 :(得分:0)

我会设置一个标记,将其标记为“就绪”。可能有更好的方法来解决这个问题,但这只是我的头脑。

<script>
    function runLoader(){
        runAjax();
        var i=0;
        var timer = setInterval(function(e){
            i++;
            //code for loading sign
            if(i==3)
                clearInterval(timer);
        } ,2000);
    }

    function runAjax(){
        var timeElapsed = false;
        setTimeout(function(){timeElapsed = true}, 6000);
        $.ajax({
            //
        }).done(function(){
            var timer2 = setInterval(function(){
                if(timeElapsed){
                    clearInterval(timer2);
                    // do X
                }
            },500);
        }
    }
</script>

答案 2 :(得分:0)

您可以创建一个在runLoader()上运行的预调用函数和runAjax()的回调函数,它将验证其他操作是否完成,然后执行操作X.示例:

var ajaxDone = false;
var loaderDone = false;
function doActionX() {
    //your action happens here
}
function tryToDoX() {
    if (ajaxDone && loaderDone) {
        doActionX();
    }
}
function runLoader(){
    loaderDone = false;
    runAjax();
    //show loading sign
    setInterval(function(e){
        //hide loading sign
        clearInterval(timer);
        loaderDone = true;
        tryToDoX();
    }, 6000);
}

function runAjax(){
    ajaxDone = false;
    $.ajax({
        //whatever
    }).done(function(){
        ajaxDone = true;
        tryToDoX();
    }
}

没有必要进行重复超时并轮询这两种状态,因为它们只完成一次(在每次运行中,即在等待时,布尔值不设置为false和true)。

编辑:这种方法可以用于任何不会间歇性地改变状态的异步代码,即使没有jQuery也是如此。