Best Practices For Heavy Computations in Javascript?

泄露秘密 提交于 2019-12-03 07:28:43

问题


I am working on client side scripts and need to do heavy computations like pushing huge number of objects in an array, it causes JavaScript to stop response and browser hangs giving an alert:

Is there any best practices or design patterns for handling these computation, I search and find many different ways to handle these situation but solutions are difficult to implement so I need best practices and easy to understand?

(I am writing code just for example But I need a general solution that is cross-browser i.e, multi-threading etc)

Example Code (series contains thousands of objects):

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

回答1:


Okay, looking at your code, there's a few things you can optimize:

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. You're getting the same "deeper" object inside chartObj multiple times --> Assign it to a temporary variable;
  2. Don't calculate the length for every iteration of the loop. Same principle as #1
  3. Assign s[series].data to a temp var. This provides a direct pointer to the data instead of having to access s[series].data each iteration of the loop. Same principle as #1
  4. jQuery is slow. For a simple loop, use JavaScript instead, especially if you're looping through a massive object.

I'm not saying this edit will work miracles, but it should reduce the load a bit.




回答2:


You should use WebWorkers

They are really supported and they are real threads in javascript as they spawn real OS threads!

Example

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 !!!
}



回答3:


You could split it in to different "threads" by using timeouts. Like so:

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 example

I guess it would prevent the warning, but I don't know how sane it really is.



来源:https://stackoverflow.com/questions/13947592/best-practices-for-heavy-computations-in-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!