有没有办法在长时间运行的JavaScript操作之前强制重排?

时间:2013-12-02 19:08:12

标签: javascript jquery html css

准备好面对强烈反对,因为我知道这是一个经常被问到的问题,并且充分意识到有更好的方法可以实现我想要实现的目标......

我在一个函数中运行了很长时间的JavaScript操作,最多可能需要10秒才能运行。我有一个“装载div”,我可以随意显示和隐藏。通常这个显示/隐藏操作非常快,但是如果我在与长时间运行的函数相同的调用链中尝试这样做,浏览器在长时间运行的函数被锁定之前没有机会重排并显示加载div

我试过了:

1 - 只显示div然后调用该函数:

$('#loadingDiv').show();
longRunningFunction();

2 - 显示div,然后调用setTimeout中的长时间运行函数,在当前函数完成后执行:

$('#loadingDiv').show();
setTimeout(function(){longRunningFunction();}, 0);

3 - 与2相同,但超时时间更长:

$('#loadingDiv').show();
setTimeout(function(){longRunningFunction();}, 100);

如果超时时间更长(比如5000毫秒),我可以显示加载屏幕,并且我的长时间运行功能可以正常执行 - 但显然这会增加执行时间,我猜不会超时浏览器兼容(只是碰巧我正在使用的浏览器碰巧在那些XXXX毫秒内重新绘制 - 另一个浏览器可能没有?)

我还尝试了一些我在SO和其他地方看到的捣蛋技巧,用于更改页面上div上的offsetLeft / offsetTop,更改self.status,但我所做的一切似乎都有相同的效果:使用页面上的旧内容锁定浏览器几秒钟,然后在长时间运行的功能完成后显示加载div。

我知道我在做什么是“错误”,但这是我现在想做的事情 - 最终我会: 1)将此代码分解为更小的块 2)可能将其移动到Web Worker中 3)加快速度,以免花费这么长时间并且不会锁定浏览器

现在有人可以建议一种简单的方法来强制在我的长时间运行操作运行之前向用户显示“加载div”吗?

3 个答案:

答案 0 :(得分:1)

使用回调:

$('#loadingDiv').show("fast", longRunningFunction);

这将在显示div后调用你的函数。

答案 1 :(得分:0)

我可能会建议为此目的使用jquery的延迟功能。为此做出的延迟对象,您可以找到有关如何使用它的教程 http://net.tutsplus.com/tutorials/javascript-ajax/wrangle-async-tasks-with-jquery-promises/

我创建了一个示例小提琴,向您展示它是如何使用的。 http://jsfiddle.net/Nemesis02/PH2nE/1/

以下是JavaScript的编写方式

(function($) {
    function initLongWait() {
        var deferred = new $.Deferred();

        setTimeout(function() {
            deferred.resolve();
        }, 2000);

        return deferred.promise();
    }

    var promise = initLongWait();
    $('#wait').fadeIn();
    initLongWait().done(function() {
        $('#wait').fadeOut();
        $('#done').fadeIn();
    });
})(jQuery);

答案 2 :(得分:0)

jsFiddle Demo

你可以采用你在#2中使用的方法,它应该可以工作。

$("#loadingDiv").show();
setTimeout(function(){
 longRunningFunction();
 $("#loadingDiv").hide();
},10);