Search code examples
javascriptwaitsleep

A better way to wait/sleep in javascript


I'm building a script in JS that will run on webpages and modify elements in a sequential order. I need to have the ability to wait/sleep while containing the entire process in a running function. The example below is self explanatory, and a very simple yet comprehensive example of what I need help with:

<body>
  <button id="button-start" onclick="updateStatus('started')">START!</button>
  <button id="button-1" onclick="console.log('step_1')">button-1</button>
  <button id="button-2" onclick="console.log('step_2')">button-2</button>

  <script>
  var status = 'stopped';
  var step = 'initial';

  function updateStatus(newStatus) {
    status = newStatus;
    script();
  }

  function wait(msec) {
    var now = new Date().getTime();
    while(new Date().getTime() < now + msec){ /* do nothing */ }
  }

  function script() {
    while (status == 'started') {
      if (step == 'initial') {
        console.log('Script started');
        step = 'click_button1';
      }

      if (step == 'click_button1') {
        document.getElementById("button-1").click();
        wait(1000)
        step = 'click_button2';
      }

      if (step == 'click_button2') {
        document.getElementById("button-2").click();
        step = 'done';
      }

      if (step == 'done') {
        status = 'stopped';
      }

    }
    console.log('Script done');
  }

  </script>    
</body>

This works exactly how I need it to but obviously using while loops is not a good idea. I've seen many other questions similar to this, but I don't understand how to adapt the other answers to address what I need help with:

  1. One central function/loop that acts on different 'steps' and has multiple different waits/sleeps within these steps
  2. Need to avoid using something that executes out of order

Solution

  • To make it look nice you could use async and a Promise which resolves after a setTimeout.

    Notice the line

    await wait(1000)
    

    <body>
      <button id="button-start" onclick="updateStatus('started')">START!</button>
      <button id="button-1" onclick="console.log('step_1')">button-1</button>
      <button id="button-2" onclick="console.log('step_2')">button-2</button>
    
      <script>
      var status = 'stopped';
      var step = 'initial';
    
      function updateStatus(newStatus) {
        status = newStatus;
        script();
      }
    
      function wait(msec) {
        return new Promise(res => {setTimeout(()=>{res()}, msec)})
      }
    
      async function script() {
        while (status == 'started') {
          if (step == 'initial') {
            console.log('Script started');
            step = 'click_button1';
          }
    
          if (step == 'click_button1') {
            document.getElementById("button-1").click();
            await wait(1000)
            step = 'click_button2';
          }
    
          if (step == 'click_button2') {
            document.getElementById("button-2").click();
            step = 'done';
          }
    
          if (step == 'done') {
            status = 'stopped';
          }
    
        }
        console.log('Script done');
      }
    
      </script>    
    </body>