Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript: Adapt synchronous code to be async, to support IE8?

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!

like image 440
Richard Avatar asked Aug 25 '15 16:08

Richard


People also ask

Is JavaScript synchronous or asynchronous?

JavaScript is a single-threaded, non-blocking, asynchronous, concurrent programming language with lots of flexibility.

How does JavaScript handle asynchronous code?

JavaScript provides three methods of handling asynchronous code: callbacks, which allow you to provide functions to call once the asynchronous method has finished running; promises, which allow you to chain methods together; and async/await keywords, which are just some syntactic sugar over promises.

Does Internet Explorer support async?

Internet Explorer IE browser version 6 to 11 doesn't supports JAVASCRIPT Async functions.


1 Answers

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.

like image 105
RadleyMith Avatar answered Oct 23 '22 03:10

RadleyMith