Reputation: 1833
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
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
Reputation: 3254
Create a non-Ajax separate process that returns data to a callback.
Browser must:
Create a separate file for your separate threaded process with the logic. This file must contain the following code:
postMessage( //data )
if(typeof(Worker) === "function") {
var worker = new Worker(//uri to js file);
worker.onmessage = function(event){
// my call back.
};
}
Upvotes: 1