@consento/promise
    TypeScript icon, indicating that this package has built-in type declarations

    1.0.7 • Public • Published

    @consento/promise

    A set of utilities for working with Promises with particular focus on abort-ability using AbortSignals.

    Goal

    Provide sturdy Promise utils that make it easier to write asynchronous code that is both performant and saves on unnecessary operations by making it easier to use AbortSignals.

    The library has a partial focus on Typescript utility as TypeScript comes with its own set of problems.

    Contributions

    Additionally to the common Consento contribution guidelines, this repository is eager to be dissolved into standard projects. If you find one of the utils presented here useful in a more common context (e.g. Node.js repo, TypeScript or w3c) then we would find it awesome if you could promote it to find its way there so we can remove it from this library.

    We also appreciate pointers to projects that may offer a better solution than the solutions presented in this repo!

    Utils

    bubbleAbort([signal: AbortSignal]): void

    Simple function that throws an AbortError if an AbortSignal happens to be aborted.

    Usage:

    const { bubbleAbort } = require('@consento/promise/bubbleAbort')
    
    async function longRunning ({ signal } = {}) {
      let result = ''
      for await (const data of internalIterator()) {
        bubbleAbort(signal) // Will throw an error if the signal is aborted
        result += data
      }
      return result
    }

    checkpoint([signal: AbortSignal]): ([input: () => T]) => T

    Allows the creation of a checkpoint function that aborts an async script if a signal is aborted.

    Usage:

    const { checkpoint } = require('@consento/promise/checkpoint')
    
    async function longRunning ({ signal }: {}) {
      const cp = checkpoint(signal)
      let result
      for (const data of internalIterator()) {
        cp() // you can use the checkpoint as-is
        result += data
    
        // passing-in a template function is going to execute that
        // template function only it the signal is not aborted.
        const foo = await cp(async () => 'bar')
      }
      return result
    }

    cleanupPromise((resolve<T>, reject, signal, resetTimeout) => () => void, [{ timeout?: number, signal?: AbortSignal}]): Promise<T>

    Versatile custom Promise implementation that allows to execute an async cleanup operation after a promise is resolved or rejected.

    Usage:

    import { cleanupPromise } = require('@consento/promise/cleanupPromise')
    
    const result = await cleanupPromise((resolve, reject, signal) => {
      setTimeout(resolve, Math.random() * 500) // Resolve & reject work like in regular promises
      setTimeout(reject, Math.random() * 500)
      const abortHandler = () => {
        reject(new Error('aborted'))
      }
      // If no signal is necessary, the signal will not be provided.
      signal?.addEventListener('abort', abortHandler)
      return () => {
        // Executed after resolve or reject is called.
        signal?.removeEventListener('abort', abortHandler)
      }
    })
    
    cleanupPromise(..., { timeout: 500, signal }) // You can also pass-in a parent signal or a timeout!
    
    cleanupPromise((resolve, reject): void => {}) // You can also use it like a regular promise

    composeAbort([signal: Signal]): { abort: () => void, signal: AbortSignal }

    Creates a new AbortController-compatible instance that can be aborted both with the abort operation and a passed-in signal.

    Usage:

    const { composeAbort } = require('@consento/promise/composeAbort')
    const { AbortController } = require('abort-controller')
    
    const main = new AbortController()
    const composed = composeAbort(main.signal)
    
    main.abort() // Will both abort main and composed
    composed.abort() // Will abort only the composed
    
    const other = composeAbort(null) // The signal is optional, allows for flexibility of an abortsignal.

    isPromiseLike(input): input is PromiseLike

    TypeScript util that helps to identify if a promise is a PromiseLike instance.

    Usage:

    import { isPromiseLike } from '@consento/promise/isPromiseLike'
    
    async function foo (input: any) {
      if (isPromiseLike(input)) {
        // do something async
      } else {
        // just sync away
      }
    }

    raceWithSignal((signal: AbortSignal) => Promise<T>[], [signal: AbortSignal]): Promise<T>

    Similar to Promise.race but aborts all promises that don't win the race.

    Usage:

    const { raceWithSignal } = require('@consento/promise/raceWithSignal')
    
    // Here the request to google will be aborted if the timeout of 500ms is reached.
    await raceWithSignal(signal => {
      return [
        fetch('http://google.com', { signal }),
        new Promise((resolve, reject) => setTimeout(reject, 500, new Error('timeout')))
      ]
    })
    
    await raceWithSignal(..., inputSignal) // You can also pass-in a signal that you maintain.

    wrapTimeout((signal?: AbortSignal, resetTimeout: () => void) => Promise<T>, [{ timeout?: number, signal?: AbortSignal}]): Promise<T>

    Wraps an async operation and passes-in a signal that will be marked as aborted when a given timeout set's in.

    Usage:

    const { wrapTimeout } = require('@consento/promise/wrapTimeout')
    
    wrapTimeout(async (signal, resetTimeout) => {
      if (signal) { // Signal may be undefined if timeout=0 is specified.
        signal.addEventListener('abort', () => {
          // now we should abort our work.
        })
      }
      resetTimeout() // With reset-timeout you can reset a given input timeout, this may be useful to delay a timeout after user interaction.
    }, { timeout: 500 })

    License

    MIT

    Install

    npm i @consento/promise

    DownloadsWeekly Downloads

    27

    Version

    1.0.7

    License

    MIT

    Unpacked Size

    58.9 kB

    Total Files

    43

    Last publish

    Collaborators

    • leichtgewicht
    • dkastl
    • rangermauve