6

I am working with a data-heavy website and I need to support IE8. I am getting some "slow-running script" errors in IE8, so I am adapting my code to pause periodically during loops for older browsers.

This is my current code:

combineData: function(xData, yData, values) {
    var combinedData = this.combineDatasets(xData, yData, values.x, values.x_val);
    combinedData = this.calculateRatiosForData(combinedData);   
    // various other data operations, then continue to set up chart...
},

calculateRatiosForData: function(data, isSpecialDenominator, x_val_key) {
    _.each(data, function(d, i) {
        // do some calculations...
    });
    return data;
},

How can I adapt calculateRatiosForData to process N rows at a time, then pause?

This will make it asynchronous, and I'm struggling to adapt my code to handle this.

Whatever I do needs to be supported in IE8, of course!

Richard
  • 62,943
  • 126
  • 334
  • 542
  • I've been reading http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call?rq=1 but I'm really struggling to understand how to adapt it to my existing code. I have a lot of synchronous functions outside `combineData`, do I really need to change them all to be asynchronous? – Richard Aug 25 '15 at 16:15
  • is there any way you do do the calculate ratios on the server? – RadleyMith Aug 28 '15 at 05:09
  • Have a look at http://stackoverflow.com/q/6864397/1048572, http://stackoverflow.com/q/714942/1048572. And yes, you will need to change everything that depends on the results of that to deal with async. – Bergi Aug 30 '15 at 21:51

1 Answers1

5

I would say to splice the data into N rows before you get into calculate ratios. Make the calculate ratios a single function ie. this part of your program // do some calculations... then promisify it using Q.

After that you can create an array of promises each promise being calculateRatiosForData(Nth row).

After that you can make a call to Promise.all(yourArrayOfCalculateRatioPromises).

The issue here is that you will still be computing all of that data on the browser. If possible it would be better to offload that processing onto the server and use a POST request for the computing. The promise structure will still look the same.

There is also the issue of whether or not you need these calculatedRatios for the rest of your script. If you don't great, if you do then you would just encapsulate the rest of the script inside of the Promise.all(arrayOfPromises).then(function (result) { //rest of script}. The key piece of that code being the .then(function () {}).

I would suggest using WebWorkers but alas they are not supported by IE8. There are workarounds found in google code and also here but I can't vouch for how well those options will work.

EDIT: this will show how to make the promise

There are basically two ways to do this.

1) You can write the calculateRatios function in the style of a node back and then promisify it using Q.

function calculateRatios (arrayInput, callback) {
    //error checking if error 
    //callback(error)

    //calculate the ratios algorithm then do
    setTimeout(callback(undefined, data), 500);
}

And then to promisify it would look like this:

var Promise = require('q'), //however you want to do this in the browser
    calculateRatiosAsync = Promise.promisify(calculateRatios);

I personally like that way because it is compatible with other control flow libraries without having to change the original function, or you can just use the original function the way you have it if it's not necessary to promisify it.

2) The other way is to explicitly create a promise.

var Promise = require('q'),
    calculateRaiosAsync = function (input) {
        var d = Promise.defer();

        //do your error checking if error
        d.reject();

        //do your calclate ratios algorithm and store the data in a variable
        setTimeout(d.resolve(yourFinishedData), 500);

        //return your promise
        return d.promise();
    }

NOTE: It should be noted that you will have to require the promise library differently, but I leave that up to you.

RadleyMith
  • 1,313
  • 11
  • 22
  • what do you want an example of... I need context. Do you want to see how to create a promise? Do you want to see how to make a POST request to the server and use promises with that? You can't really make a large computation in the brower not a large computation in the browser unless you make the algorithm more efficient or you offload it to the server. – RadleyMith Aug 28 '15 at 18:52
  • Thanks! I just literally want to see how to adapt `calculateRatiosForData` so it will calculate 1000 rows at a time, then pause for half a second, and not return till it's finished. In a way that works in IE8. I definitely don't want to POST anything to the server. The large calculation in the browser works fine in all modern browsers. – Richard Aug 29 '15 at 18:36