npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@consento/promise

v1.0.7

Published

Helpful utilities to work with AbortController/-Signal.

Downloads

16

Readme

@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