12

私はクライアント側のスクリプトに取り組んでおり、膨大な数のオブジェクトを配列にプッシュするなどの重い計算を行う必要があります。これにより、JavaScript が応答を停止し、ブラウザがハングして警告が表示されます。

ブラウザの警告

これらの計算を処理するためのベスト プラクティスまたは設計パターンはありますか。これらの状況を処理するためのさまざまな方法を検索して見つけましたが、ソリューションを実装するのは難しいため、ベスト プラクティスと理解しやすいものが必要ですか?

(例としてコードを書いていますが、クロスブラウザー、つまりマルチスレッドなどの一般的なソリューションが必要です)

コード例 (シリーズには何千ものオブジェクトが含まれています):

for (var series = 0; series < chartObj.masterChart.series.length; series++) {
    var detailData = [];
    jQuery.each(chartObj.masterChart.series[series].data, function (i, point) {
        if (point.x >= chartObj.RangeSelectedMinValue && point.x <= chartObj.RangeSelectedMaxValue) {
            detailData.push({
                x: point.x,
                y: point.y
            });
        }
    });
    chartObj.detailChart.series[series].setData(detailData);
}
4

3 に答える 3

5

さて、あなたのコードを見ると、最適化できることがいくつかあります:

var s = chartObj.masterChart.series, // #1
    sLength = s.length,              // #2
    chartMin = chartObj.RangeSelectedMinValue,
    chartMax = chartObj.RangeSelectedMaxValue;
for (var series = 0; series < sLength; series++) {
    var detailData = [],
        data = s[series].data,       // #3
        length = data.length;        // #2
    for(var i = 0; i < length; i++){ // #4
        var point = data[i];
        if (point.x >= chartMin && point.x <= chartMax) {
            detailData.push({
                x: point.x,
                y: point.y
            });
        }

    }
    chartObj.detailChart.series[series].setData(detailData);
}
  1. chartObj 内で同じ「より深い」オブジェクトを複数回取得しています->一時変数に割り当てます。
  2. ループの反復ごとに長さを計算しないでください。#1と同じ原理
  3. s[series].data一時変数に割り当てます。s[series].dataこれにより、ループの各反復にアクセスする代わりに、データへの直接ポインターが提供されます。#1と同じ原理
  4. jQuery は遅いです。単純なループの場合は、特に大量のオブジェクトをループする場合は、代わりに JavaScript を使用してください。

この編集で奇跡が起こると言っているわけではありませんが、負荷が少し軽減されるはずです。

于 2012-12-19T08:04:53.247 に答える
4

WebWorkersを使用する必要があります

それらは実際にサポートさ れており、実際の OS スレッドを生成するため、javascript の実際のスレッドです!

main.js

var heavy_process = new Worker('heavy_process.js');

heavy_process.addEventListener('message', function(e) {
  // Log the workers message.
  console.log(e.data);
}, false);

heavy_process.postMessage();

Heavy_process.js:

for (var series = 0; series < chartObj.masterChart.series.length; series++) {

  var detailData = [];
  jQuery.each(chartObj.masterChart.series[series].data, function (i, point) {
      if (point.x >= chartObj.RangeSelectedMinValue && point.x <= chartObj.RangeSelectedMaxValue) {
        detailData.push({
            x: point.x,
            y: point.y
        });
      }
  });
  chartObj.detailChart.series[series].setData(detailData);
  // you should use self.postMessage here !!!
}
于 2016-02-22T18:40:56.593 に答える
2

タイムアウトを使用して、異なる「スレッド」に分割できます。そのようです:

var counter;

function longRun(start) {
    counter = 0;

    for (var i = start; i < 3000; i++) {

        counter++;
        console.log(i);
        if (counter > 99) {
            setTimeout(function() {
                longRun(i+1)
            }, 0);
                console.log('counter at: ' + i + ' start fake "thread"');
            return;
        }
    }
    alert('Done!');
}
longRun(0);​

jsFiddle の例

警告を防ぐと思いますが、それが本当にどれほど正気かはわかりません。

于 2012-12-19T08:26:24.923 に答える