JavaScript 没有立即更新 DOM

发布于 2024-12-07 12:26:00 字数 1172 浏览 0 评论 0原文

我的问题与这篇文章中描述的问题非常相似:

Javascript 进度条不会“即时”更新,而是在进程完成后立即更新?

我有一个调用一些服务并处理一些操作的脚本。 我正在尝试创建一个进度条,向最终用户指示脚本执行的当前状态。我计算进程 (#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 调用周围设置 setTimeout 函数,但似乎没有任何效果。

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

有什么想法吗?

谢谢,

My question is very similar to the one described in this post:

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

I have a script that calls a few services, and processes some actions.
I'm trying to create a progressbar that indicates the current status of script execution to the end user. I calculate the process (#currentaction / #totalactions) to indicate the progress and update the DOM each time an action is processed with this new value.

However, the DOM is only updated when all actions are finished.
I have placed a setTimeout in my function, and for some reason the DOM is still not updating step by step, it's only updating when the entire jscript is executed.

here's an example of my 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);
}

I've tried setting the setTimeout function around the entire CreateObject call, around the DOM calls only, but nothing seems to do the trick.

I'm probably missing something very obvious here, but I really don't see it.

Any ideas?

Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

回忆那么伤 2024-12-14 12:26:00

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

因此,本质上,500 毫秒内不会发生任何事情,然后所有更新都会立即发生(当然,从技术上讲,是按顺序发生的)。

尝试使用此方法将每个函数调用间隔 500 毫秒进行排队。

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

并从 CreateObject 中删除 setTimeout 调用。

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

The reason your code isn't working properly is that the CreateObject function will be called several times over in quick succession, each time immediately cueing up something to do 500ms later. setTimeout() doesn't pause execution, it merely queues a function to be called at some future point.

So, essentially, nothing will happen for 500ms, and then all of your updates will happen at once (technically sequentially, of course).

Try this instead to queue up each function call 500ms apart.

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

and remove the setTimeout call from CreateObject.

Note the use of an automatically invoked function to ensure that the variable i within the setTimeout call is correctly bound to the current value of i and not its final value.

屌丝范 2024-12-14 12:26:00

我认为您所做的不仅仅是 CreateObject 中的 setTimeout ?
如果不是,最好从循环中调用 setTimeout。

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

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

由于这将调用它自己的更新代码,因此它可能会解决问题。没有您的完整代码,我无法准确说出这里的问题是什么。我也是 PrototypeAPI 负责人,而不是 JQuery 负责人。

I presume you are doing more than just the setTimeout within CreateObject ?
If you are not, best just to call the setTimeout from the loop.

I suspect you are using JQuery. If so, try using animate

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

Since that will invoke it's own updating code, it might solve the issue. Without your full code, I couldn't say exactly what the problem here is. I'm also a PrototypeAPI head and not a JQuery head.

你的笑 2024-12-14 12:26:00

@gazhay:您可能认为使用 jQuery 的 .animate 函数可以绕过这个问题。

不过,我找到了解决这个问题的办法。我修改了 JScript,不再使用 for 循环,而是使用递归函数。显然,直到 FOR 循环完全终止后,DOM 才会更新......任何人都可以确认这一点吗?

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

这不起作用:

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);

@gazhay: you probably have a point that using the .animate function of jQuery this problem could have been bypassed.

However, I found a solution for this problem. I modified the JScript to no longer use a for loop, but use recursive functions instead. Appearantly the DOM does not get updated untill the FOR loop is completely terminated... Can anyone confirm this?

I've tested this out with the following script:

This doesn't work:

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

While this does work:

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

var i = 0;
dostuff(i);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文