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

最善の解決策は、Webワーカーを使用することです。これにより、UIの更新とはまったく異なるスレッドで処理を実行できます。Webワーカーなしでブラウザーをサポートする必要がある場合は、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 に答える
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 update 呼び出しを試行するたびに、より多くの作業単位を実行することをお勧めします。おそらく、実行する作業のキューを作成し、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 に答える