有没有一种方法可以在长时间运行的JavaScript操作之前强制回流

Is there a way to force a reflow before a long-running JavaScript operation?

本文关键字:操作 JavaScript 运行 长时间 一种 方法 有没有      更新时间:2024-01-20

准备好面对反弹了,因为我知道这是一个经常被问到的问题,并且充分意识到有"更好"的方法来实现我想要实现的目标。。。

我在一个函数中有一个长时间运行的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) 加快速度,这样就不会花那么长时间,也不会锁定浏览器

但是目前有人能建议一种简单的方法,在我的长期运行操作运行之前,强制向用户显示"loadingdiv"吗?

使用回调:

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

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

我可能会建议为此目的使用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);

jsFiddle Demo

你可以采取你在#2中使用的方法,它应该有效。

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