1

How to stop javascript for executing for some specific time period? Using setTimeout function am able to execute a block of statements after a delay but during the wait time the statements next to the setTimeout are being executed. Can I suspend this synchronous execution.

As per requirement I have setTimeout function in a for loop. But during the wait time the loop is being executed.

Here is the sample code:

for(i = 0;i < n;i++){
    setTimeout(function(){
        // Accessing the loop variable i inside this function
    },3000);
}

http://jsfiddle.net/KK2mq/2/

Tom Fenech
  • 72,334
  • 12
  • 107
  • 141
Pranav
  • 446
  • 2
  • 6
  • 1
    You need to use a closure, not to 'pause' current thread http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – A. Wolff Mar 13 '14 at 11:30
  • 1
    As it stands, it is unclear what you are trying to do. Is your problem simply that the value of `i` isn't what you wanted? Do you want to pause execution of the rest of the script? Do you want the numbers to appear one by one? – Tom Fenech Mar 13 '14 at 11:48
  • If your problem is that you want to pause *the loop itself*, then this is probably what you are after: [How do I add a delay in a JavaScript loop?](http://stackoverflow.com/a/3583740/1446005) – RandomSeed Mar 13 '14 at 13:02

2 Answers2

2

You can use a closure so that the correct value of i is used:

for (let i = 0; i < 5; i++) {
  let divId = document.getElementById("withTimeout");
  (function(i) {
    if (i % 2 == 0) setTimeout(function() {
      divId.innerHTML += i + " ";
    }, 3000);
  })(i);
}

for (let i = 0; i < 5; i++) {
  let divId = document.getElementById("withoutTimeout");
  if (i % 2 == 0) {
    divId.innerHTML += i + " ";
  }
}
<h3>with timeout</h3>
<div id="withTimeout"></div>
<h3>without timeout</h3>
<div id="withoutTimeout"></div>

This results in both of your output showing the same values. But were you hoping that the numbers appear 3 seconds after one another? If so, you can do this:

(function display(i, step, max) {
  let divId = document.getElementById("withTimeout");
  setTimeout(function() {
    divId.innerHTML += i + " ";
    i += step;
    if (i <= max) display(i, step, max);
  }, 3000);
})(0, 2, 4);
<div id="withTimeout"></div>

The display function is recursive, calling itself every 3 seconds after displaying the previous number, as long as i <= 4. The (...)(0, 2, 4) around the whole thing mean call this function immediately, with the arguments (0, 2, 4).

Tom Fenech
  • 72,334
  • 12
  • 107
  • 141
  • I want the numbers in "withTimeOut" div to appear one after other with delay. I had tried using while loop to create delay but of no use. The code is like : var timeAfterDelay = new Date().getTime(); while(new Date().getTime() < timeAfterDelay){} – Pranav Mar 20 '14 at 06:16
  • @Pranav I have added a solution that shows the numbers one by one. – Tom Fenech Mar 20 '14 at 11:52
0

The only way of suspending a thread I know of is synchronous ajax, and even that is deprecated. With jQuery that looks like:

$.ajax("/quickOne?arg="+arg,{async:false,success:d=>result=d});

But maybe you can make do with starting new detached threads with delay as in the first answer. With ES6 you can use a coroutine that looks consequential and keeps the context. The only gotcha is that the main thread will run ahead, without waiting on anything, but the computation with delays will proceed in a different thread in parallel. Example:

var bgthread=function*(){
    console.log("Starting a computation with delays");
    $.post("/serverside",response=>{
        processResult(response);
        bgthread.next();
    });
    setTimeout(function(){bgthread.next()},3000);
    console.log("yielding 1");
    yield;
    console.log("yielding 2");
    yield;
    console.log("All computations done");
}()//links
bgthread.next();//start the coroutine in background
MKaama
  • 1,732
  • 2
  • 19
  • 28