setTimeout不能强制浏览器立即重新绘制

setTimeout can not force browser to repaint immediately

本文关键字:新绘制 绘制 不能 浏览器 setTimeout      更新时间:2023-09-26

我想用setTimeout逐个突出显示一些单词。它适用于Chrome和Firefox(在Firefox中,即使没有setTimeout, ajax也可以逐个突出显示)。但它在IE或Safari中不起作用,它们仍然在JS代码完成后显示所有高亮。JS代码为:

for(var k=0;k<MAX;k++) {            
    (function (_k) {                
        setTimeout( function() {
        $.ajax({
            //do something
            success: function(data, textStatus, jqXHR) {  
                //using wrap <span> tag to highlight words according to ajax return data
            }
        }); } ,2000);
    }) (k);
}

我只是想让浏览器重新绘制页面并立即显示高亮,问题是什么?非常感谢!

setTimeout()$.ajax()都启动异步进程,然后立即继续到下一行。因此,您的for循环将在任何超时运行之前完成,并且在任何ajax成功回调运行之前完成,并且所有超时都计划在循环结束后运行2000毫秒,即或多或少在同一时间。

如果您希望每一个都在前一个之后两秒发生,那么在开始下一个之前等待前一个ajax请求完成,或者通过将延迟乘以循环计数器来增加每个后续超时的超时延迟:

for(var k=0;k<MAX;k++) {            
    (function (_k) {                
        setTimeout( function() {
          $.ajax({
            //do something
            success: function(data, textStatus, jqXHR) {  
                //using wrap <span> tag to highlight words according to ajax return data
            }
          });
        } , 2000 * k);     // <--- this line is the only change
    }) (k);
}

这样第一次超时是0毫秒,第二次是2000毫秒,第三次是4000毫秒,等等。

演示:http://jsfiddle.net/gsRL7/

你在做的是"拖延一切"。就像

// Say you have these values
var a = 1, b = 2, c = 3;
// The loop is technically doing
a+=1, b+=1, c+=1;
// And the end effect is the same. They're still in line.
a == 2;
b == 3;
c == 4;

你可能想在每个项目上都做setInterval,这样每个标记就会彼此延迟。

var timer = setInterval(function(){
  // do what you need to do here as if in the loop
  if(k >= MAX) clearInterval(timer);
});

同样,你不能指望"立即"。看到这里有一个AJAX调用,如果网络阻塞,那么"立即"是不可能的。

在您的代码中,您跳过了会导致或中断重绘的确切行(或显示延迟重绘是实际问题还是我们正在查看更深层次的内容)。

element.offsetWidth;这样的显式几何访问通常有助于解决不必要的渲染优化,如果是这种情况的话。