skip to Main Content

I have an async function which I used in sorting visualizer. I want to add a feature of pause and unpause. I tried to use a while(isTrue){} (isTrue is a usestate variable) but this method is making the page unresponsive. Is there any better way to add this feature?

   import asyncSetTimeout from '../helpers/asyncSetTimeout';

const bubbleSort = async ({
  array,
  setArray,
  setColorsArray,
  visualizationSpeed,
  setI,
  setJ,
  setNum1,
  setNum2,
  comparisons,
  setComparisons,
  swaps,
  setswaps,
  isTrue
} = {}) => {
  comparisons=0;
  swaps=0;
  let len = array.length;
  for (let i = 0; i < len - 1; i++) {
    setI(i);
    for (let j = 0; j < len - 1 - i; j++) {
      setJ(j);
      let newColorsArray = new Array(len).fill(0);
      newColorsArray[len - 1 - i] = 3;
      newColorsArray[j] = 1;
      newColorsArray[j + 1] = 2;
      setColorsArray(newColorsArray);
      await asyncSetTimeout({
        timeout: 10 * visualizationSpeed
      });
      setNum1(array[j]);
      setNum2(array[j + 1]);
      comparisons++;
      setComparisons(comparisons)
      if (array[j + 1] < array[j]) {
        let temp = array[j + 1];
        array[j + 1] = array[j];
        array[j] = temp;
        swaps++;
        setswaps(swaps)
        setArray(array);
      }
      await asyncSetTimeout({
        timeout: 10 * visualizationSpeed
      })
      while(isTrue){}
      console.log(isTrue);
    }
  }
  setColorsArray([])
};

export default bubbleSort;

2

Answers


  1. Put an await inside the while loop

    while(isTrue) {
         await asyncSetTimeout({
            timeout: 100
         });
    }
    

    In this way you don’t break the Event Loop and the page doesn’t freeze.

    This is the fastest solution based on your design. More elegant ways need a different approach to the function design.

    Login or Signup to reply.
  2. I would recommend an async generator –

    async function* bubbleSort(array) {
      let swapped;
      do {
        swapped = false;
        for (let i = 0; i < array.length - 1; i++) {
          if (array[i] > array[i + 1]) {
            [array[i], array[i + 1]] = [array[i + 1], array[i]];
            swapped = true;
          }
        }
        yield array; // ✅ yield single step of work
      } while (swapped);
    }
    

    Now you can use for await..of to step through the generator, displaying one step at a time –

    const array = [5, 3, 1, 4, 2];
    for await (const sortedArray of asyncBubbleSort(array)) {
      console.log(sortedArray); // ✅ display one unit of progress
    }
    

    To add pause behaviour, we can define a controller that allows us to interrupt, pause,

    let controller = // ... ✅
    
    const array = [5, 3, 1, 4, 2];
    
    for await (const sortedArray of asyncBubbleSort(array)) {
      if (controller.cancelled) break // ✅
      await controller.promise // ✅
      console.log(sortedArray);
    }
    
    controller.pause()   // ✅ pause action
    controller.unpause() // ✅ unpause action
    controller.cancel()  // ✅ cancel action
    

    Implementation of the controller might look like this –

    const controller = {
      cancelled: false,
      promise: null,
      pause() {
        this.promise = new Promise(r => void 0)
      },
      unpause() {
        this.promise = null
      },
      cancel() {
        this.cancelled = true
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search