DEV Community

Discussion on: setTimeout is a callback-style function. What would happen if we change that?

Collapse
 
joelnet profile image
JavaScript Joel

This is a fantastic question. Without cancellable promises, you would not be able to cancel the setTimeout.

For a majority of use cases cancelling a promise is not needed. Though that doesn't mean it is not a valid use case. Throttling and debouncing is an example of a valid use case when you would want to cancel a promise.

The sleep implementation I created currently does not support cancellation. I have created an issue for this here: github.com/joelnet/MojiScript/issu.... This is a feature that would be great to have.

Here's a very naive implementation that could support cancellation:

const sleep = milliseconds => value => {
  let timeoutId
  const cancel = () => clearTimeout(timeoutId)
  const promise = new Promise(resolve => {
    timeoutId = setTimeout(() => resolve(value), milliseconds)
  })
  return Object.assign(promise, { cancel })
}

(async () => {
  // create promise and cancel
  const promise = sleep (1000) ('Uh oh!')
  const { cancel } = promise

  // promise to log when resolved
  promise.then(console.log)

  // cancel promise
  cancel()

  console.log('Done.')
})()

Bluebird also supports promise cancellation: bluebirdjs.com/docs/api/cancellati...

Converting this Promise to use bluebird's Promise would also work.

Collapse
 
maxart2501 profile image
Massimo Artizzu

Yes, that could work! 🙌

You can also consider the approach that's been taken for cancelling a fetch promise: it's based on a "signal" that's being created by an AbortController object:

const ctrl = new AbortController()
const signal = ctrl.signal
fetch(someUrl, { signal })
  .catch(error => {
    console.log(error.name)
  })

// Later on...
ctrl.abort()
// Then it logs 'AbortError'

You can extend your sleep function to accept a signal option and listen to an abort event. Although it does seem a little overkill for something like this...

Thread Thread
 
joelnet profile image
JavaScript Joel

This is interesting. I'll have to create some test project with the .cancel and an AbortController. Maybe I'll create a debounce to compare the differences.

Definitely something to think about.