在javascript函数中更新进度指示器

时间:2012-06-24 23:51:38

标签: javascript progress

(请参阅底部的更新)

我已经查看过几十个问题而无法完成这项工作。

鉴于下面的代码,如何在每次迭代后强制它更新我的简单进度指示器($(“#log”))?

编辑:我认为这个JSFiddle举例说明了我的问题:http://jsfiddle.net/kPRky/

这是HTML:

<div id="test"></div>
<div id="log"></div>

这就是函数的调用方式:

$("#test").html(createLevelMap());

这就是功能

function createLevelMap() {
    var height = 300;
    var width = 1000;
    var totalpixels = height * width; //used for calculating loading percentages;
    var currentpixel = 0; //used for calculating loading percentages;

    var x = 0;
    var y = 0;
    //lots of other variables

    for (x = 0; x < width; x += 1) {
        for (y = 0; y < height; y += 1) {

            //lots of calculations with lots of variables

            currentpixel += 1;
            $("#log").html((currentpixel / totalpixels) * 100 + "%");
        }
    }

    return ('done'); //actually returns a very long base64 encoded string
}

更新

我简化了它,以便我有一个单独的函数来渲染每一列,而不是整个网格。但是,使用setTimeout仍然不会导致正确显示进度。

for (x = 0; x < width; x += 1) {
    $("#log").html(((x + 1) / width) * 100 + "%<br>(sliver " + (x + 1) + "/" + width + ")");
    setTimeout(createSliver(x), 100);
}

^^这导致我期望的输出,但没有百分比更新。我将其更改为setTimeout(function(){createSliver(x)},100);按照评论中的建议然后我甚至没有得到我的输出(也仍然没有增加百分比)。

3 个答案:

答案 0 :(得分:0)

这个怎么样?

var height = 300;
var width = 1000;
var totalpixels = height * width; //used for calculating loading percentages;
var currentpixel = 0; //used for calculating loading percentages;

incrementAndUpdate(currentpixel, totalpixels);

function incrementAndUpdate(currentValue, totalPixels) {
    $("#log").html((currentValue / totalPixels) * 100 + "%");
    if (currentValue < totalPixels) {
        setTimeout(function () { incrementAndUpdate(currentValue + 1, totalPixels); }, 1);
    }
}

鉴于此速度很慢,我建议你可以用较少的频率调用它,并在每次尝试setTimeout / html更新调用时做更多的工作单元。也许创建一个要做的工作队列,并在你的incrementAndUpdate函数中,选择直接调用函数,或者通过setTimeout。

像这样......

function incrementAndUpdate(currentValue, totalPixels) {
    $("#log").html((currentValue / totalPixels) * 100 + "%");

    // do a bit of work.

    if (currentValue < totalPixels) {
        var workFunction = function () { incrementAndUpdate(currentValue + 1, totalPixels); }
        if (currentValue % 100 == 0)
            setTimeout(workFunction, 1);
        else
            workFunction();
    }
}

这可以完成相同的工作,但是通过较少的setTimeout次调用可以更快地完成工作。您可以调整调用setTimeout的频率,以便尽可能优化用户体验。

以下是您的小提琴的更新:http://jsfiddle.net/kPRky/1/

答案 1 :(得分:0)

最好的解决方案是使用Web Workers。这使您可以在完全不同的线程中运行处理UI更新。如果您需要支持没有Web worker的浏览器,则需要使用setTimeout为GUI更新提供运行的机会。

如果使用超时方法,您可以通过设置最大时间来获得最佳体验,然后在断开循环并调用setTimeout之前让它运行。这将让GUI重新绘制。

这里有一个例子:http://jsfiddle.net/kPRky/6/

您可以通过在somethingSlow方法中添加/删除零来加快/减慢速度。

答案 2 :(得分:0)

所以我通过从内部调用setTimeout()函数来获得更新的进度。这是我失踪的关键。

现在是基本格式:

function nextRow() {
    x += 1;
    setTimeout(function () { createSliver() }, 100);
    if (x < width) { setTimeout(function () { nextRow() }, 100); }
}

function createSliver() {
    //do stuff here
    currentpixel += 1;
    $("#log").html(((currentpixel) / totalpixels) * 100 + "%<br>(pixel " + (currentpixel) + "/" + totalpixels + ")");
    y += 1;
    if (y < height) {
        setTimeout(function () { createSliver() }, 100);
    } else {
        y = 0;
    }

function mainFunction() {
        setTimeout(function () { nextRow() }, 100);
        return (data);
}

但是现在我的“数据”没有正常回归。我假设因为现在一切都在异步运行......大便。