Javascript不会立即更新DOM

时间:2011-10-03 13:12:22

标签: javascript html dom

我的问题与本文中描述的问题非常相似:

Javascript progress bar not updating 'on the fly', but all-at-once once process finished?

我有一个调用一些服务的脚本,并处理一些操作。 我正在尝试创建一个进度条,指示最终用户的脚本执行的当前状态。我计算进程(#currentaction / #totalactions)以指示进度,并在每次使用此新值处理操作时更新DOM。

但是,只有在所有操作完成后才会更新DOM。 我在我的函数中放置了一个setTimeout,由于某种原因,DOM仍然没有逐步更新,它只在整个jscript执行时才更新。

这是我的JScript的一个例子

    var pos = RetrievePos();
_TOTALCOUNT = (pos.length);

for(var i = 0; i < pos.length; i++) {
    var cpos = pos[i];
    CreateObject(cpos, id);
}

function CreateObject(cpos, id)
{
    setTimeout(function() {
        //do work here, set SUCCESS OR ERROR BASED ON OUTCOME
        ...

        //update gui here
        var scale = parseFloat(_SUCCESS + _ERRORS) / parseFloat(_TOTALCOUNT);
        var totWidth = $("#loaderbar").width();
        $("#progress").width(parseInt(Math.floor(totWidth * scale)));
    }, 500);
}

我已经尝试围绕整个CreateObject调用设置setTimeout函数,只围绕DOM调用,但似乎没有什么可以做的。

我可能在这里遗漏了一些非常明显的东西,但我真的没有看到它。

有什么想法吗?

谢谢,

3 个答案:

答案 0 :(得分:4)

您的代码无法正常工作的原因是CreateObject函数会快速连续多次调用,每次立即提示500分钟后执行某些操作。 setTimeout() 不会暂停执行,它只会将某个函数排队,以便在将来某个时间调用。

因此,基本上,500毫秒不会发生任何事情,然后您的所有更新都会立即发生(当然,技术上也是如此)。

尝试这样做,将每个函数调用排队500ms。

for (var i = 0; i < pos.length; i++) {
    setTimeout((function(i) {
        return function() {
            var cpos = pos[i];
            CreateObject(cpos, id);
        }
    })(i), i * 500);
}

并从setTimeout移除CreateObject来电。

注意使用自动调用的函数来确保setTimeout调用中的变量i正确绑定到i当前值而不是其最终值

答案 1 :(得分:0)

我认为你在CreateObject中做的不仅仅是setTimeout吗? 如果不是,最好只是从循环中调用setTimeout。

我怀疑你正在使用JQuery。如果是这样,请尝试使用动画

$('#progress')。animate({width:parseInt(Math.floor(totWidth * scale))},'slow');

因为那将调用它自己的更新代码,它可能会解决问题。如果没有完整的代码,我无法确切地说出这里的问题是什么。我也是一个PrototypeAPI头,而不是JQuery头。

答案 2 :(得分:0)

@gazhay:您可能有一点,使用jQuery的.animate函数可以绕过这个问题。

但是,我找到了解决此问题的方法。我修改了JScript以不再使用for循环,而是使用递归函数。看起来DOM没有得到更新,直到FOR循环完全终止......任何人都可以确认这个吗?

我用以下脚本对此进行了测试:

这不起作用:

for(var i = 0; i < 1000; i ++)
{
    setTimeout(function() {document.getElementById('test').innerHTML =  "" + i;}, 20);
}

虽然这确实有效:

function dostuff(i)
{
    document.getElementById("test").innerHTML = i;
    if(i<1000)
        setTimeout(function(){ dostuff(++i);}, 20);
}

var i = 0;
dostuff(i);