Reputation: 53
There has to be an easy way to do this, but I'm new to JS.
I have a javascript program that (1) takes user input, (2) updates the webpage based on that input, then (3) performs a lengthy calculation. The trouble is that the webpage doesn't register the update till after the lengthy calculation. Isn't there a way to pause execution so that the page can update before the long calculation?
I've tried setTimeout and window.setTimeout, but they made no difference.
The program is for playing a game: the user inputs a move, the script updates the position, then calculates its next move. postMessage prints text messages using div.innerHTML; buttonFn takes the input from the user, updates the position, prints a message, then starts the computer calculating.
function buttonFn(arg){
var hst = histButt;
hst.push(arg);
var nwmv = hst.clone();
postMessage("New move: " + nwmv.join());
if(status == opposite(comp) && !pauseQ){
var mvsposs = movesFromPos(posCur,status);
if(mvsposs.has(nwmv)){
updatePosCur(nwmv);
//waitasec();
if(comp == status && !pauseQ){
compTurn();
};
}
else{
histButt = nwmv;
};
};
};
Upvotes: 3
Views: 3172
Reputation: 379
If you only need to support modern browsers (or if you use a transpiler), you can now use ES6 features to make this much easier and more in the style the original questioner was trying to do. (I realize the question is 8 years old - no harm in a new, more current answer!)
For example you can do something like this:
// helper function to use a setTimeout as a promise.
function allowUpdate() {
return new Promise((f) => {
setTimeout(f, 0);
});
}
// An infinitely looping operation that doesn't crash the browser.
async function neverStopUpdating(someElement) {
let i = 0;
while (true) {
someElement.innerText = i;
i++;
await allowUpdate();
}
}
If you're trying to do a hard computation you'll want to make sure not to do this await too frequently - in this example, in Chrome at time of writing, i
only increments by about 150 per second because the context switch of a setTimeout is not fast (where you'd get hundreds of thousands in a second if you didn't yield for updates). You'd likely want to find a balance, either always perform some number of iterations before allowing an update, or maybe eg. call Date.now() in your loop and yield for an update whenever 100ms have passed since the last time you allowed an update.
Upvotes: 3
Reputation: 9950
JavaScript is single threaded. If you do your calc server side you could get the results via ajax which is called asynchronously, not blocking your ui.
Upvotes: 0
Reputation: 4691
yes there is, call your function like this. Using setTimeout will allow a page reflow prior to your JS executing.
function buttonFn(arg){
var hst = histButt;
hst.push(arg);
var nwmv = hst.clone();
postMessage("New move: " + nwmv.join());
if(status == opposite(comp) && !pauseQ){
var mvsposs = movesFromPos(posCur,status);
if(mvsposs.has(nwmv)){
updatePosCur(nwmv);
//waitasec();
if(comp == status && !pauseQ){
setTimeout(function(){
compTurn();
},0);
};
}
else{
histButt = nwmv;
};
};
};
Remember, JS is very event driven friendly. If you can move things off, and call them later do it. Thats the only way we can support multi-threaded like behavior.
Upvotes: 6
Reputation: 207501
You can do the update, wait for a bit of time, than do the calculation.
OR
You can use webworkers on browsers that support them.
Without having actual code, that is the best answer that I can give you.
Upvotes: 0