0

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
T Mack
  • 950
  • 3
  • 12
  • 27
  • 3
    You're looking for promises. – SLaks Jul 18 '17 at 00:39
  • 2
    Use `setTimeout` which you can wrap into a `DelayPromise`: https://blog.raananweber.com/2015/12/01/writing-a-promise-delayer/ – Dai Jul 18 '17 at 00:40
  • 1
    Could you not utilise the setTimeout functionality where you then call the same function again with different flagged inputs? – Jonathan Holland Jul 18 '17 at 00:40
  • Change your central loop to a recursive function and it will integrate well with asynchronous callbacks – Bergi Jul 18 '17 at 00:59

1 Answers1

2

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>
E. Sundin
  • 4,103
  • 21
  • 30
  • This is perfect! I'm actually writing this for my Electron app but it doesn't look like it supports ES6 yet. I found this package https://www.npmjs.com/package/asyncawait but I'm having some trouble getting it to work :/ Thanks for the answer! – T Mack Jul 18 '17 at 01:42