2

I have an async function that has a loop that I need to be able to pause or unpause it. This is what I have so far.

I use a flag to pause the flow:

let flag = true;

function flag_func() {
    flag = !flag;
}


$(document).ready(function () {
    function sleep(ms) {
        while (!flag) {
            //...waiting.. but infinite loop 
        }
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    async function show_simulation(data) {
        document.getElementById("solve-button").outerHTML = "<button type=\"button\" id='pause-button' onclick='flag_func()' class=\"btn btn-primary btn-lg\">Pause</button>";
        //simulation
        if (data.length === 0) {
            console.log('stuff')
        } else {
            let i;
            for (i = 0; i < data.length; i++) {
                await sleep(40);
                // do stuff
            }
        }
    }
});

The problem is that is being paused, but due the while block the flow, I can't unpause the for loop.

Any idea about how I can solve this?

5
  • @bigless I know that, I said it in the question Commented Jul 18, 2018 at 23:01
  • unless I'm mistaken, this approach won't work. the while(!flag){...} will continue running forever, and because JS is single threaded that means that no other code will ever run. Why do you need the while(!flag) loop? If we know the purpose, we might be able to figure out a different solution. Commented Jul 18, 2018 at 23:20
  • @PunDefeated, was my approach to pause the loop Commented Jul 18, 2018 at 23:23
  • @exsnake ah okay, so you’re looking for something to replace the sleep function, not the while(!flag) ? Commented Jul 18, 2018 at 23:26
  • @PunDefeated I'm looking for something to replace the while, something like 'wait the button to be pressed' Commented Jul 18, 2018 at 23:31

2 Answers 2

3

It might be a nice use case for async iterables. It involves a bit of boilerplate to create your async list, but then the code is much nicer. Basically you would have:

import AsyncList from './async-list.js'

const sleep = (ms) => new Promise(r => setTimeout(r, ms));

async function f(data) {
  const list = new AsyncList(data);

  document.getElementById("btn-toggle").addEventListener("click", function () {
    if (list.paused) {
      this.textContent = "Pause";
      list.resume();
    } else {
      this.textContent = "Resume";
      list.pause()
    }
  })


  for await (let item of list) {
    console.log(item)
    await sleep(1000);
  }
  console.log("end of loop")
}

f([10, "hello", 1029, 90, 80, 209, 44])

A possible implementation of AsyncList could be:

export default class AsyncList {
  constructor(array) {
    // shallow copy
    this._array = array.slice();

    this._index = 0;
    this._length = this._array.length;
    this.paused = false;
    this._resume = () => {}; // noop, in case `resume` is called before `pause`
  }

  [Symbol.asyncIterator]() {
    return this;
  }

  pause() {
    this.paused = true;
  }

  resume() {
    this.paused = false;
    this._resume();
  }

  next() {
    if (this._index < this._length) {
      const value = this._array[this._index++];

      if (this.paused) {
        return new Promise(r => this._resume = r.bind(null, { value }))
      }

      return Promise.resolve({ value })
    } else {
      return Promise.resolve({ done: true });
    }
  }
}

Just to give to you the idea, you could also encapsulate the private properties, and check more scenarios (here I assume data is an array, for example, not just an iterable).

Sign up to request clarification or add additional context in comments.

Comments

0

I'd replace:

    let i;
    for (i = 0; i < data.length; i++) {
        await sleep(40);
        // do stuff
    }

...with...

    let i = 0;
    const doStuff = () => {
      // do stuff

      if (++i < data.length) {
        setTimeout(doStuff, 40);
      }
    };

    setTimeout(doStuff, 40);

2 Comments

have you noticed this: async function show_simulation(data) { ? it's an async function, thus the await keyword.
I noticed. My point was I didn't see any good reason to be using async/await.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.