20

is there a function that would add a time delay between 2 lines of code. Not the settimeout, because settimeout requires a function/object in its arguments.

I am looking for something like this pseudo code

write "abc";
delay(500);
write "xyz";

TIA

Edit: jimr's solution in my other thread worked for my purpose, and so is Robusto's.

I am just wondering why the "sleep" methods given by Robusto and CMS's link are not preferred. How would that be different than the settimeout method since they both introduce a pause in the code? (settimeout pauses before the function is executed, the sleep method pauses before the next line is executed.)

Community
  • 1
  • 1
Jamex
  • 732
  • 3
  • 9
  • 17
  • 1
    See also: http://stackoverflow.com/questions/951021/javascript-sleep – Christian C. Salvadó Jun 15 '10 at 20:26
  • http://www.neilmix.com/narrativejs/doc/ – Ates Goral Jun 15 '10 at 21:23
  • 1
    The reason it is not recommended is already given by Tobias P.: “JavaScript execution blocks the browser, so a sleep-Method would block the browser for 500msec, do you really want to have your browser not responding for half an second?” Your response is: “settimeout does not work for what I am trying to do.” Now my question is: what are you trying to do? Perhaps there's a more efficient way to deal with your actual issue, than using this `delay` method (and don't forget to use [@first-name](http://meta.stackexchange.com/questions/43019) in comment replies). – Marcel Korpel Jun 15 '10 at 22:28
  • 3
    If setTimeout does not work for you, that means you need to rethink your code. Using the delay code is like using a hammer to open a window. – epascarello Jun 15 '10 at 23:26
  • Now we can use aync/await (es6). see my answer below. – Rohith K P Mar 17 '19 at 11:47

10 Answers10

20

The following is clunky and ugly and I would never do it in my own code and I DO NOT RECOMMEND IT AT ALL, but it shows that such a thing is possible.

// time arg is in milliseconds
function delay(time) {
  var d1 = new Date();
  var d2 = new Date();
  while (d2.valueOf() < d1.valueOf() + time) {
    d2 = new Date();
  }
}
Robusto
  • 31,447
  • 8
  • 56
  • 77
  • lol I was writing a custom sleep myself on jsfiddle, and it works really ugly :) – Anurag Jun 15 '10 at 21:44
  • 20
    This is a terrible, terrible, terrible idea. I would like to fill up the comment block, in fact, with the word "terrible", but somebody would probably mod out the comment. **Burning time on somebody else's CPU is rude**. At **least** have the function refuse to "delay" for more than 1/4 second or so (250ms). Still rude, but at least it's pretty brief. – Pointy Jun 15 '10 at 22:34
  • @Pointy: Hence my preface "ugly and clunky"; I just wanted to show that something like what the OP asked for *is* technically possible. I would never do this in my own code. – Robusto Jun 16 '10 at 12:44
  • 3
    I hate to say it publicly , but due to some reasons beyond my control I need a sync delay in Test specs. Thanks for this – basarat Jun 27 '13 at 04:47
  • 2
    And it is helpful with debugging complex ui bugs. Just to hold up execution at certain places to get a clue about what is going on when. – Murrah Sep 16 '16 at 09:10
  • 1
    Agree with @Murrah -- I was looking for something to force a delay in execution in order to insure I wasn't succumbing to some timing bugs. This is not useful for real code, but it's very useful for testing. Thanks! :) – xmnboy Mar 23 '17 at 01:35
14

You can use setTimeout so that it almost appears the code runs on two lines:

write('abc')
setTimeout(function() {
write('xyz')
},500)
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
12

A sleep-Method is not available because JavaScript execution blocks the browser, so a sleep-Method would block the browser for 500msec, do you really want to have your browser not responding for half an second?

Use setTimeout as suggested.

Tobias P.
  • 4,537
  • 2
  • 29
  • 36
  • Thanks, but settimeout does not work for what I am trying to do. – Jamex Jun 15 '10 at 20:45
  • 10
    @Jamex yes it does - you just have to adjust what you want to do. Burning CPU time in a busy loop is a profoundly bad idea, especially when you're doing it to somebody else's computer. – Pointy Jun 15 '10 at 22:35
5

In JavaScript 1.7, using yield with async.js, you can do the following:

var yourFunction = _(function () {
    write("abc");
    yield to.sleep(.500);
    write("xyz");
});
Eli Grey
  • 35,104
  • 14
  • 75
  • 93
3

I don't know what you're trying to do here, but here's one concrete reason for why a custom sleep may not work for your purposes assuming the browser freezing up is a non-issue for you.

Are you manipulating the DOM by any chance between those two write commands? If you are, then it simply will not work (as perceived by an end user), although the DOM nodes will be constructed/updated in memory, the display will not get updated as that part is not synchronous. The processor is locked up in that loop, and both the DOM updates will refresh on screen when that loop finishes. See this example.

Ideally, you should see "Hello", and after 5 seconds, "World" on the screen. However, on Chrome, Safari, and Firefox, you would see both "Hello" and "World" at the end of 5 seconds. The console logs prove that the DOM node is constructed in memory, but is not refreshed on screen until the end as you can see yourself.

Marcel Korpel
  • 21,536
  • 6
  • 60
  • 80
Anurag
  • 140,337
  • 36
  • 221
  • 257
  • I was trying to do a document.onclick and grab the id of whatever element that I clicked on. The problem was that after the settimeout, the click event was lost. Another user (jimr) was kind enough to write a short routine that preserves the event for me. I don't know JS syntax enough to understand good codes. I only write pseudo logic codes and try to search for the correct syntax, but it is difficult to google for answers if I don't know the key words/ideas. Thanks. – Jamex Jun 16 '10 at 00:21
  • 2
    @Jamex - I think if you update the question with the details from your above comment, you'll get a lot more helpful and better answers once users understand the problem better. – Anurag Jun 16 '10 at 01:19
  • @Jamex (and Anurag) – I think this original question is [already answered](http://stackoverflow.com/questions/3048005/document-onclick-settimeout-function-javascript-help/3048965#3048965) in the other question you referred to (though not perfectly). – Marcel Korpel Jun 16 '10 at 01:49
1

As far as I know, setTimeout() is the only way to do it.

function write(out) {
  alert(out);
}

// ...

write('abc');
setTimeout(function() { write('xyz')}, 500);
Hooray Im Helping
  • 5,194
  • 4
  • 30
  • 43
1

ES6 Introduced async/await which can be used to have an actual delay. I have answered this in a different post, just updating here as well

An async function can contain an await expression that pauses the execution of the async function and waits for the passed Promise's resolution, and then resumes the async function's execution and returns the resolved value.

    async function delay(delayInms) {
      return new Promise(resolve  => {
        setTimeout(() => {
          resolve(2);
        }, delayInms);
      });
    }
    async function sample() {
      console.log('a');
      console.log('waiting...')
      let delayres = await delay(3000);
      console.log('b');
    }
    sample();
Rohith K P
  • 3,233
  • 22
  • 28
0

I miss that on javascript too, as a java SE and EE enthusiast not having my sleep() makes me disappointed with JavaScript, I made a timer and I hope it can be useful to you, it uses jQuery, and it's fairly simple, you can reverse engineer it and create something that meet your needs:

function timer(object, time) {
  $(object).attr({
    'onclick': ''
  });
  if (time < 0) {
    $(object).attr({
      'onclick': "timer('#clock', 6000);"
    });
    return;
  }
  $(object).animate({
    opacity: 1
  }, 1, function() {
    $(object).empty();
    $(object).append(time + 'ms');
    time--;
    timer(object, time);
  });
}
#clock {
  width: 65px;
  height: 20px;
  border: 1px solid #F00;
  text-align: center;
  line-height: 20px;
  background-color: #000;
  color: #FFF;
  font-weight: 900;
}
<!DOCTYPE html>
<html>

<head>
  <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
  <title>HTML5, CSS3 and JavaScript demo</title>
</head>

<body>
  <div id="clock" onclick="timer('#clock',6000);">--s</div>
</body>

</html>
Kyle
  • 1,568
  • 2
  • 20
  • 46
0
setInterval(function delay{ //loops every 300 milliseconds
   setTimeout(function firstLineOfCode(){ //waits 100 milliseconds then runs code
      write('abc');
   },100)
   setTimeout(function secondLineOfCode(){ //waits 200 milliseconds (100 after previous line) then runs code
      write('def');
   },200)
   setTimeout(function thirdLineOfCode(){ //waits 300 milliseconds (100 after previous line) then runs code
      write('ghi');
   },300)
},300) //loops after total of delays in function delay()
yan
  • 1
0

You can add delay using async await concept in JavaScript.

const add2SecondsDelay = () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('added 2 seconds delay);
    }, 20000);
  });
}

async function asyncFunctionCall() {

  console.log('abc'); // ------> first step
  const result = await add2SecondsDelay();
  console.log("xyz"); // ------> second step will execute after 2 seconds

}

asyncFunctionCall();
p.durga shankar
  • 967
  • 8
  • 18