Home > Software engineering >  Disabling the button when waiting for async function to be aborted
Disabling the button when waiting for async function to be aborted

Time:01-10

How can i disable the button when waiting for the Promis function sort to be aborted. For now i managed to put here delay it works good when i put like 50 numbers to sort but for bigger ammout of number it doesnt work how can i make it scalable that this functionality works for all dataset sizes:

let isActive = false
let controller = new AbortController()

startButton.addEventListener('click', async () => {
  if (! isActive) {
    isActive = true
    startButton.textContent = 'Stop'
    startButton.style.backgroundColor = 'red'

    try {
      const sort = SelectAlgorithm(data, algorithmType)
      await sort(updateBars, controller.signal)
      svg.selectAll('rect').style('fill', 'black')
    } catch (err) {
      if (err instanceof DOMException && err.name === 'AbortError') {
        console.log('Sorting function aborted')
      } else {
        throw err
      }
    }
  } else {
    startButton.disabled = true
    isActive = false
    startButton.textContent = 'Wait ...'
    startButton.style.backgroundColor = 'grey'
    startButton.style.cursor = 'not-allowed'
    controller.abort()

    await delay(500)

    startButton.textContent = 'Start'
    startButton.style.backgroundColor = 'green'
    startButton.disabled = false
    startButton.style.cursor = 'pointer'
  }

  isActive = false
  startButton.textContent = 'Start'
  startButton.style.backgroundColor = 'green'

  controller = new AbortController()
})

CodePudding user response:

You haven't learned how HTML forms work, from the looks of it. You don't attach "click" handlers to buttons if you can avoid it -- in the kind of problem you seem to be solving, at least, you're just making it harder for yourself with that "click" handler.

Instead, use a form and the "submit" event which will ensure your submit button, when disabled, won't even trigger, which is exactly what you want and is something you don't need to program yourself much.

Also don't muck about with changing colours of buttons in JavaScript -- just make sure your button can be targeted with CSS when in another state -- disabled, for instance -- and have a CSS rule targeting it so that when it's disabled its appearance may change automatically.

You should also have separate "Start" and "Stop" buttons because that's far more manageable than having to "mutate" the "Start" button into a "Stop" button -- rest assured CSS can help you hide your [disabled] "Start" button so that things appear as if the "Start" button turned into a "Stop" button, while in reality the former was simply hidden and the second was then accordingly shown.

<form>
     <button>Start</button>
     <button disabled name="stop" type="button">Stop</button>
</form>
form button:not([type]):disabled {
    background-color: red;
}
form.addEventListener("submit", async ev => {
    ev.submitter.disabled = true; /// The form won't submit again while its only submit button is disabled
    ev.target.elements.stop.disabled = false;
    try {
        const sort = SelectAlgorithm(data, algorithmType);
        await sort(updateBars, controller.signal);
        svg.classList.add("sorted"); /// Much better than changing the `fill` with JS -- now you can rely on CSS doing the same thing more efficiently and the way it was designed to
    } catch (err) {
        if (err instanceof DOMException && err.name == 'AbortError') {
            console.log('Sorting function aborted');
        } else {
            throw err;
        }
    } finally {
        ev.submitter.disabled = false; /// When done
        ev.target.elements.stop.disabled = true;
    }
});

Also please stop habitually using the strict equality operator, === -- even if you know exactly what it is for and haven't just copied and pasted a snippet much like unfortunately thousands of them using === that must have sprung up from some viral blog post of a code-bro 10 years ago, the strict equality operator not only isn't needed above, it's also an eye-sore and makes reading the code harder (because it's specific) -- == will suffice fine in your and most other use cases of code that isn't some low level library that needs to distinguish null from undefined or accommodate for some other JavaScript idiosyncrasies.

I've seen your kind of code be employed by people over and over again, and it is not a sustainable way to do it. Normally you should always try to contain form elements like buttons inside form elements, you get a lot of useful (assistive, not the least) behaviour for free and don't need to reinvent the wheel. Buttons and other controls that are not part of form elements (or associated with one), are only ever needed in a very narrow subset of [exceptional] use cases.

CodePudding user response:

Ok i manged to do this i dont know it is good way to do this but it works :

...
let sortingPromise: Promise<unknown>

startButton.addEventListener('click', async () => {
    if (!isActive) {
       ...
        try {
            const sort = SelectAlgorithm(data, algorithmType)
            sortingPromise = sort(updateBars, controller.signal)
            svg.selectAll('rect').style('fill', 'black')
            await sortingPromise
        } catch (err) {
            if (err instanceof DOMException && err.name === 'AbortError') {
                console.log('Sorting function aborted')
            } else {
                throw err
            }
        }
    } else {
        ...
        await sortingPromise.catch(() => {}) // wait for the function to abort
        ...
    }
    ...
})
  • Related