nullUser
nullUser

Reputation: 1833

How to write simple asynchronous function in javascript

I want to call a javascript function that takes a long time (5 seconds) to finish without freezing my client's browser. They click the button to start the operation, then they should be notified when it finishes. Currently I have written something like

$(document).ready(function(){
    $('#tokenbutton').click(function(){

        // IMMEDIATE EFFECT
        $('#tokenbutton').attr("disabled",true).val("Computing...");

        var callback = function(resultsFromExpensiveOperation){
            // CALLBACK EFFECTS
            $('#tokenbutton').val("Token computed");
            $('#submitbutton').attr("disabled",false);
            // ...
        };                  

        // FREEZES BROWSER
        doExpensiveOperation(callback);
    });
});

and

doExpensiveOperation = function(callback){
    // ...
    //var results = ...

    callback(results);
};

but this freezes my browser when I run it. How can I change it so this doesn't freeze my browser?

Upvotes: 0

Views: 117

Answers (2)

QBM5
QBM5

Reputation: 2788

There are no real asynchronous is javascript, thus no multi thread or anything like that. There is a way to make long running function not freeze the browser in certain cases though.

You can use the setInterval or setTimeout function to do small bits of your long running task at a time, thus each bit takes a fraction of a second and then the ui becomes responsive again for a fraction of a second until the next bit runs. This functionally makes the ui stay responsive and does not add much time (if any) onto the processing of the code. For example.

long running code

function doSomething(){
   for(var x = 0; x < 10000; x++){
      // do something 
   }
}
// doing it like this could take forever and lock up the browser

broken up code

var total = 0;
setTimeout(doSomething, 4);

function doSomething(){

     for(total = total; total + 100 < 100; total++){
        // do something 
     }
     if(total < 10000){
        setTimeout(doSomething, 4);
     }
}
// doing it like this stops the browser from freezing but does not save any time.

A few things, I put a time of 4 ms into the setTimout because that is actually the lowest value js will except, even if you put 1 it defaults to 4.

I used a setTimeout pattern instead of a setInterval to prevent the next interval from running before the previous on finishes.

And lastly this pattern does not work for everything. It lends itself best to loop and sequence based operations.

Hope it helps

Upvotes: 1

Pete
Pete

Reputation: 3254

Use Case

Create a non-Ajax separate process that returns data to a callback.

Solution

Requirements

Browser must:

  • Support HTML5
  • Support Web Workers

Structure

Create a separate file for your separate threaded process with the logic. This file must contain the following code:

postMessage( //data )

Code

if(typeof(Worker) === "function") {
    var worker = new Worker(//uri to js file);
    worker.onmessage = function(event){
        // my call back.
    };
}

Upvotes: 1

Related Questions