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

deferrals

v1.0.5

Published

A way to globally define promises that you can await at multiple locations.

Downloads

8

Readme

DEFERRALS

Deferrals is a very simple library that enables the creation of any number of promises which can then be awaited in any other code in your app.

de·fer·ral (noun) /dəˈfərəl/ : a postponement of an action or event. act of putting off to a future time.

Installation

npm i deferrals

yarn add deferrals

Usage Example

// Import the library
const {
  makeDefer,
  waitForDefer,
  resolveDefer
} = require("deferrals");

// Some functions we'll run later
const await1 = async() => {
  const value = await waitForDefer("Defer1");
  console.log(value);
}

const await2 = async() => {
  const value = await waitForDefer("Defer2");
  console.log(value);
}


// Create the first deferral
makeDefer('Defer1');

// Just for fun, create another one!
makeDefer('Defer2');

// Call the 2 functions above - they're promises,
// and will not run until their promises are resolved.
await1();
await2();

// Simulate an async action after 1 second
setTimeout(() => {
  resolveDefer("Defer1", "Defer 1 Resolved!");
}, 1000);

// and another after 2 seconds
setTimeout(() => {
  resolveDefer("Defer2", "Defer 2 Resolved!");
}, 2000);

Example for the equivalent of an async constructor:

const {
  makeDefer,
  waitForDefer,
  resolveDefer
} = require("deferrals");

class SomeAsyncWrapper {
  // Private field property!
  #deferName
  constructor(defername) {
    this.#deferName = name
    makeDefer(this.#deferName);
    this.isready = waitForDefer(this.#deferName);
    init()
  }
  async init() {
    // do DB stuff in async mode
    resolveDefer(this.#deferName);
  }
}


const myWrapperInstance = new SomeAsyncWrapper("mydbthing");

const mainfunction = async() {
  await myWrapperInstance.defer;
  // now you know the init() function has finished, whever you use myInstanceWrapper!
}

Uses (why the hell does this exist?)

The reason this little project even exists came from a simple question posted on a programming discord: "How do I turn off every even handler in my bot while waiting for my database to reconnect"

The question prompted me to remember what I was previously doing with my JOSH and Enmap modules : the defer concept, which returned a promise that only resolved when my initialisation (connecting to the database, opening tables, etc) was completed. I realised this pattern was useful and I hadn't actually seen it before in javascript, though it exists in Golang.

Some specific advantages of deferrals over "regular promises"

  • A deferral can be reset by calling makeDefer again with the same name, effectively turning into a "stop and wait, or go" trigger you can control externally.
  • You do not need to import the actual promise - importing waitForDefer and using the same deferral name means any code in your project, globally, can wait for any deferral created, resolved, or rejected, from any other location in your code.
  • You can have a list of active deferrals, so you know what promises are being waited on currently.

So, there are a few places where a deferral can be used effectively:

  • You need a number of functions, events, loops, or any code, to wait for an external trigger to be called (either individually, as a group, or globally).
  • You need to shut off all processing on events, streams, or modules, but not lose the incoming event data from calls (in other words, not just "return" which loses the progress in the code).
  • You need to wait for several external triggers to synchronize processing.

Documentation

makeDefer (name: string) : null

Creates a deferral with a specific name (must be a string name) and returns the promise for that deferral.

The promise returned by makeDefer will not resolve or reject on its own. Only one deferral can be created with the same name. If makeDefer is called again with the same name, the promise will be reset to pending state.

resolveDefer (name: string) : null

Resolves a deferral with the specified name. The promise is set to a resolved state and any code waiting for the deferral will then trigger.

The deferral name is then deleted from the list (will not appear in listDefers)

If the deferral of that name does not exist, nothing happens.

rejectDefer (name: string) : null

Rejects the deferral with the specified name. The promise is set to a rejected state and any catch() or try/catch for this deferral will then trigger.

The deferral name is then deleted from the list (will not appear in listDefers)

If the deferral of that name does not exist, nothing happens.

waitForDefer (name: string) : Promise<void> | null

Attempts to get a deferral by name. If the deferral exists, returns a promise which will remain in a pending state until it's rejected or resolved through the above methods. If the deferral does not exist, returns a promise that instantly resolves to prevent locking the process.

listDefers () : string[]

Gets a list of defers that are currently pending, as an array of names as strings. Can be looped over to resolve, reject, or any other action.