1

Background:

The following code demonstrates that the alert function blocks the operation of setTimeout:

// clock time
function now(){ return (new Date()).getTime() } 

var start = now(),
    elapsed_before_interruption

// This will interrupt the function below
setTimeout(function(){
    elapsed_before_interruption = now()-start   
    alert('Paused')
    start = now()
}, 2000)


setTimeout(function(){
  var elapsed_since_interruption = now() - start
  var elapsed = elapsed_since_interruption + elapsed_before_interruption

  // drop < 1/100s from display
  var t = Math.round(100 * elapsed / 1000)/ 100

  // Always finishes ~4 seconds after (i.e has been interrupted)
  alert( 'Elapsed time: ' + t 's' )

}, 4000)

fiddle

This makes for an excellent pause mechanism when I am choreographing various function calls based upon predetermined intervals.

My question:

Can this be done without calling alert?

EDIT Whilst similar to the following question: What is the JavaScript version of sleep()? the responses to that question predominantly make the assumption that the OP is dealing with a scheduling issue and suggest code restructuring. I would like to keep this question up as I am specifically not asking for advice on working with promises etc.

By means of explanation, I am writing single web pages (only my code) that are used to conduct timed response latency trials. There are many moving parts and I can implement pause by simply writing

function pause(){ alert('paused') }

I however have to introduce the ugly browser dialog. Anyway to avoid this?

Community
  • 1
  • 1
Joe
  • 1,455
  • 2
  • 19
  • 36
  • So you completely want to pause all execution for a period of time? – Mike Cluck May 19 '16 at 21:46
  • Exactly. `alert` appears to achieve this. Is that functionality available to developers or only for browser dialogs? – Joe May 19 '16 at 21:48
  • Possible duplicate of [What do I do if I want a JavaScript version of sleep()?](http://stackoverflow.com/questions/951021/what-do-i-do-if-i-want-a-javascript-version-of-sleep) – Mike Cluck May 19 '16 at 21:48
  • It's certainly similar, but I imagine that `alert` is not tearing through the CPU cycles whilst it waits unlike the function in that question. – Joe May 19 '16 at 21:54
  • No but the idea is the same and there are more solutions than just burn out the CPU while waiting. The best solution is to restructure your code so you use something like a `setTimeout`. – Mike Cluck May 19 '16 at 21:55
  • I guess that my point is that if I have multiple interacting 'modules' that are all using `setTimeout` then I will need a whole notification infrastructure to implement the pause. Also any currently running `setTimeouts` will be ignored unless they all have inbuilt polling (to see if they should be paused). `alert` does all of this in a single line. – Joe May 19 '16 at 21:58
  • 2
    You shouldn't block all Javascript from executing just because *you* want *your* Javascript to wait on something. – Ingo Bürk May 19 '16 at 22:00
  • I know for a fact that my javascript will be the only thing running on the page. `alert` does it! The question is can I, without the ugly dialog. – Joe May 19 '16 at 22:04
  • @IngoBürk Just thinking about it there are very conceivable scenarios where you would want to block someone else's javascript. Suppose I get a countdown timer component from vendor X but they do not have pause functionality. `alert` would come to the rescue. Also, if you should not block all javascript from running then you should probably never use `alert` – Joe May 19 '16 at 22:23
  • Even though you deny it, your problem seems to be *exactly* a scheduling issue. Restructure your code (we can help you with that). – Bergi May 19 '16 at 23:02
  • @Bergi. I will try to explain why it cannot be converted to a scheduling issue. I have several d3.js components built by someone else. The components render an animation based upon some data. The api for the component only has `start` functionality. I can hijack the thread using `alert` causing the animation to freeze completely. Is there another way that does not involve rewriting all the components? – Joe May 23 '16 at 10:11
  • You should be able to hijack the underlying asynchronous primitives that those d3 components use - `setTimeout` or `requestAnimationFrame` or whatever, maybe even some `d3` system function. Overwrite them with your own functions that hold back the callback when you want the animation to stop. – Bergi May 23 '16 at 13:18

1 Answers1

1

The very short answer: Don't do it this way. If you need to control the order of async processes, there are a variety of better ways.

  • For debugging, use the Chrome dev tools to set a breakpoint. Much easier.

  • If you want to wait for something specific, approaches like Promises, callbacks, and libraries like async or queue are relatively easy to use and more flexible.

  • If you want the syntactical simplicity of waiting in the middle of a function, try precompiling your code with babel and using the async/await syntax, which behaves in a similar way to what you have here (though you need to wait for something specific).

Note that none of these are "true thread blocking". There's only one thread in JS (unless you're using Workers or similar); you can block it with something like while(true) {}, but it locks everything in your browser window, including user interactions. You don't actually want that.

nrabinowitz
  • 55,314
  • 10
  • 149
  • 165
  • My problem is not with order control. I actually have a lot of async processes wired up using promises. However because I am trying to use a web browser to produce timed response experiments then the ability to pause and resume execution would be ideal. Javascript does give `alert` to help with this. Just wondered if there was a programmatic equivalent. – Joe May 19 '16 at 22:01
  • `while(true)` can also lock up your PC. I'll stick to `alert` if it's ugly dialog vs CPU death. – Joe May 19 '16 at 22:03
  • @Joe: Just insert a `.then(pauseIfNecessary)` into all your promise chains at the places where you would want to pause, and use a flag to toggle what `pauseIfNecessary` does. – Bergi May 19 '16 at 23:04