3

I have a long running javascript code that process some kind of render (webgl). It's some kind of "adaptative rendering" in which i calculate a surface more and more precisely over time (meaning that the "resolution" of the scene becomes more and more precise).

I want it to run as long as the user doesn't press a key, or move the mouse. As stated here, i could use setTimeout or setInterval, to give some time to javascript to process other events.

I've tested setTimeout and setInterval delays on this jsFiddle, and i observe the following result:

setTimeout delay: 15-20 ms
setInterval delay: 2-4 ms

It's fast, but still quite hard to use in my situation. I need to be able to react, finish some computations and render in 16 ms to give the user the impression to run at 60 fps.

So here's the question(s):

1) Is there some other (more clever) way to check if there are some incoming user input events to be processed ?

2) Is there something else i can use to make some "long running code interruptible by user" ? (maybe web workers ?)

Community
  • 1
  • 1
Sebastien
  • 682
  • 1
  • 14
  • 26

1 Answers1

2

You have to break your code into small chunks and run each chunk on a timer tick. In between each timer tick, user events can be processed and you can set a flag if you want the execution of the long running timer driven process to stop.

There is no other way to process events or check for pending events. You have to yield back to the main event loop which means your javascript thread of execution needs to finish. And, then the only way you can execute some more code after yielding back to the event loop is to either respond to an event or use a timer. This is just the way javascript is written and architected.

Your only other choice is to use web workers, but they can't touch the DOM, don't work in older browsers and can only communicate with the main event loop via messsage passing. Good for doing computations, but not for doing animation.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I was thinking of something along these lines too...would it be done with a `while (true)` loop that checked the current time on each iteration, to see if the designated amount of time had elapsed? – Matt Browne Mar 08 '13 at 00:56
  • @MattB. - you could regularly check the elapsed time in your long running code stop processing every 500ms or so if you wanted, set a timer for the next iteration and then return back to the event loop. That would help control the length of time each chunk of code runs (regardless of speed of computer), but you will still obviously have to finish execution to allow any pending event to be processed and then resume execution on a timer. – jfriend00 Mar 08 '13 at 00:59
  • So, if i understand correctly, i'm forced to use setTimeout or setInterval to manage thoses "timer ticks" ? And in that case, can i be sure that the events will be processed ? – Sebastien Mar 08 '13 at 02:38
  • @Seb37 - yes, you are forced to use timers to allow event processing (you must return from your execution thread to allow events to process) if you can't do your work from web workers which are the only real threads that javascript has. As best I know events are processed in FIFO order so all events that occurred before a timer event would get processed before the next timer tick. This sometimes delays your timer callback if processing the events takes a bunch of time. – jfriend00 Mar 08 '13 at 02:43
  • Okay, fair enough. I'm not very happy with this solution, but as you pointed out, it seems to just be the way javascript is architected. I think the best solution in my case is to compute until i find the render "acceptable", then process the rest smoothly with timer chunk. Thank you, jfriend00. – Sebastien Mar 08 '13 at 16:49