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?
-
What kind of "expensive operation" are we talking about? 5 seconds of processor time on an ordinary modern computer is a LOT of processing.Pointy– Pointy2014年07月07日 17:18:09 +00:00Commented Jul 7, 2014 at 17:18
-
1Pretty sure you can't do this in a browser since there's only a single JS thread. In the past, I've chunked it up and had a timer fire so I can resume on the next chunk. Ironically, it's a poor man's threading.David Ehrmann– David Ehrmann2014年07月07日 17:21:16 +00:00Commented Jul 7, 2014 at 17:21
-
developer.mozilla.org/en/docs/Web/Guide/Performance/…Bart– Bart2014年07月07日 17:27:31 +00:00Commented Jul 7, 2014 at 17:27
-
@Bart Support for web workers seems to be ok, but not amazing. You'll probably miss 15% of browsers.David Ehrmann– David Ehrmann2014年07月07日 17:31:42 +00:00Commented Jul 7, 2014 at 17:31
-
Asynchronous execution of JavaScript in browsers is only possible with WebWorkers. But as David Ehrmann says, asynchronicity is not necessary to prevent freezing of the browser. stackoverflow.com/questions/672732/…Robert– Robert2014年07月07日 17:32:20 +00:00Commented Jul 7, 2014 at 17:32
2 Answers 2
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
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.
};
}
1 Comment
typeof Worker == "function"?