1

オブジェクトの配列があり、この配列を一度に 1 つのオブジェクトでループし、その配列内の各オブジェクトが特定の基準を満たしているかどうかを確認するためにいくつかのチェックを行い、そのオブジェクトがこの基準を満たしている場合は、このオブジェクトのプロパティをコピーします配列に入力します (そのプロパティには別のオブジェクトも含まれます)。

for(var v = 0; features.length > v; v++){
   var feature = features[v];
    //If the feature is on the map then we want to add it
    if(feature.onScreen()){     
        dataArray.push(feature.attributes); 
    }
}

なんらかの理由で、このオブジェクトの配列のサイズが大きい (5000 以上) 場合、この操作は非常にコストがかかり、ブラウザは 1 ~ 2 秒 (場合によってはそれ以上) ロックアップします。

私はコードが何をするかについてもっと詳しく知ることはできませんが、このループを考えると、ブラウザに休憩を与える最良の方法は何だろうと思っていました.500回の反復ごとに言うと、ロックアップせずに続行します等

ありがとう

4

4 に答える 4

0

ループの構造を次のように変更します。

var index = 0;
function myfunc() {
   while(features.length > index){
       var feature = features[v];
       //If the feature is on the map then we want to add it
       if(feature.onScreen()){     
          dataArray.push(feature.attributes);

       }
       index++;
       //You can do this
       var waitingTime = 0;
       If (index% 500=0) waitingTime=100; //or 10, 20...
       //Or just with a short interval
       var waitingTime = 10;
       setTimeOut('myfunc', waitingTime);
   }
}

またはパラメータを使用:[私はこれを好む]

function myfunc(index) {
    if(!index) {
       index=0;
    }

    while(features.length > index){
       var feature = features[v];
       //If the feature is on the map then we want to add it
       if(feature.onScreen()){     
          dataArray.push(feature.attributes);
       }
        //You can do this
       var waitingTime = 0;
       If (index% 500=0) waitingTime=100; //or 10, 20...
       //Or just with a short interval
       var waitingTime = 10;
       setTimeOut('myfunc', waitingTime);
   }
}

[編集]通話を
変更...setTimeOut

そして、あなたのコードでは、関数を呼び出すときに、インデックスを初期化するためにパラメーターを指定しないでください!

于 2013-03-27T10:53:10.947 に答える
0

わかりません...しかし、そのコードを関数に入れてから、関数を取り出して呼び出すのはどうですか(たとえば、xMごとに)?

例えば、

var LastPos = 0;

function DoLoop()
{


    for(var v = LastPos; features.length > v; v++){
                var feature = features[v];
                //If the feature is on the map then we want to add it
                if(feature.onScreen()){     
                    dataArray.push(feature.attributes);

                }

               if(v > 500)
               {
                   LastPos = v;
                   break;
               }
    }
    setTimeout('DoLoop()', 10);
}
于 2013-03-27T10:54:34.597 に答える
0

少しのバーストと少しの再帰で何かをしたとしたらどうなるでしょうか:

フィドルコード

主な機能

何が起こるかは、与えられた間隔 (つまり 500) で渡され、与えられた反復回数でループを終了するindexと、同じバースト番号で自分自身を呼び戻します。features 配列の最後が完了すると、関数は終了します。burstforburst

var transferFeatures = function (index, burst) {
    for (var z = 0; z <= burst; z++) {
        if (index === features.length) {
            return;
        }

        var feature = features[index];

        if (feature.onScreen) {
            dataArray.push(feature.attributes);
        }
        index++;
    }
    if (index !== features.length) {
        transferFeatures(index, burst);
    }
};

テスト

負荷をシミュレートするために、さまざまなキーと値のペア (最も重要なのはattributes内部オブジェクト)を使用してオブジェクトの配列を作成しました。

//To simulate a random boolean
var randomBoolean = function () {
    return Math.random() <= 0.5;
};

//A random integer
var getRand = function () {
    return (Math.floor(Math.random() * 10).toString());
};

// Create a bunch of dummy objects
var randomFeatures = function (arr, i) {
    for (var p = 0; p < i; p++) {
        arr.push({
            onScreen: randomBoolean(),
            attributes: {
                width: getRand(),
                height: getRand(),
                someAtt: "I'm just an attribute",
                coolKidsRideBikes: true,
                foo: "bar",
                bar: "baz"
            }
        });
    }
};

確かに、これはonScreen()使用するテストと同じではありませんが、どちらにしてもboolean値に評価されます。この概念をコードに適用すると、驚くべき結果が得られると思います。

私がリンクしたフィドルのすべては、一番上にある次のように呼び出されます。

randomFeatures(features, 5000);
console.log(features.length);
transferFeatures(0,500);
console.log(dataArray.length);

負荷テスト

ofを使用し5000000て (500 万個の) ランダムなオブジェクトがプッシュされるようにシミュレートfeaturesしたところ、スクリプトは約 3.29 秒で完了しました。 burst1000シミュレートされた負荷

于 2013-03-27T13:52:46.327 に答える
0

setTimeOut() はこれを解決できます。

var maxStatement = 1000, currentIndex=0, timeoutVar = ''
var sLimit = features.length

function multiStepLoop(){
    for (var i=currentIndex; i<currentIndex+maxStatement; i++){
        //---DO YOUR STUFFS HERE
    }

    var a = sLimit-i;
    currentIndex += maxStatement;
    if (maxStatement >= a){ maxStatement=a }
    if (a<=0){
        callBackFunction() //-- function to call when your peocess finish.
    }else{
        timeoutVar = setTimeout('multiStepLoop()',1)
    }
}
multiStepLoop();

欠点は、このプロセスが完了した後にやりたいことをすべて関数にまとめてから、callBack_Function のように実行する必要があることです。

注 : setTimeout の時間を 1 ミリ秒に設定する必要があります。ブラウザは待機中のカーソルを表示しません。

于 2013-03-27T10:58:56.370 に答える