1

(请参阅底部的更新)

我已经查看了几十个问题,但无法完成这项工作。

鉴于下面的代码,我如何强制它在每次迭代后更新我的简单进度指示器 ($("#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); 按照评论中的建议,然后我什至没有得到我的输出(也仍然没有增加百分比)。

4

3 回答 3

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

​</p>

鉴于此速度较慢,我建议您可能以较少的频率调用它,并在每次尝试 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/

于 2012-06-25T00:08:26.560 回答
0

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

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

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

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

于 2012-06-25T01:49:38.283 回答
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);
}

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

于 2012-06-25T03:35:36.313 回答