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

promise-registry

v0.0.7

Published

Creates a registry of promises to which promises can be registered and from which promises can be obtained.

Downloads

10

Readme

promise-registry

A global registry of promises, and a factory for registries.

With a registry you can:

  • Register promises (with register)
  • Obtain registered promises (with once)
  • Obtain promises that aren't registered yet (with once)

To use the global registry, use once and register.

Create a new registry with makeRegistry. It will have its own once and register functions.

OK, so what?

This lets you:

  • Give promises a global name
  • Treat promises like events
  • Wait for promises that haven't even been made yet
  • Use a promise in a completely different place from where it is generated, without the plumbing to pass it around

I don't like bullet points. Talk to me.

Sometimes you need to depend on asynchronous behavior but it isn't convenient to pass promises around as values. As long as modules use the same registry and the same name, they get the same promise. Also, being able to get a promise by name before it is registered removes the need to coordinate the creation of that promise.

This can be particularly useful for asynchronous dependencies during e.g. initialization.

Steps have names.

init.js

const { register, once } = require('promise-registry');
const appSettings = require ('./app-settings.js');
const cookies = require ('./cookies.js');

// init/app-settings-loaded is used in ui.js but registered here.
register('init/app-settings-loaded', appSettings.load());

// init/cookies-accepted is registered in ui.js but used here.
const cookiesInitialized = once('init/cookies-accepted').then(cookies.init);
register('init/cookies-initialized', cookiesInitialized);

Dependencies and dependents can be declared separately.

ui.js

const { register, once } = require('promise-registry');
const userMessage = require('./user-message.js');
const loadUserSettings = require('./user-settings.js');

// init/cookies-accepted is used in init.js but registered here.
register('init/cookies-accepted', userMessage.waitForAcceptCookies());

// init/cookies-initialized and init/app-settings-loaded 
//   are registered in init.js but used here.
const userSettingsLoaded = Promise.all([
    once('init/cookies-initialized'),
    once('init/app-settings-loaded')
]).then(([cookies, appSettings]) => loadUserSettings(cookies, appSettings));

It's all loaded in the right order as long as the registries (including the global one) and names match up.

Installation

Via npm:

npm install promise-registry --save

In Node.js:

const promiseRegistry = require('promise-registry');

Usage - Default Registry

Using the default registry lets you use the global node module cache to ensure you're using the same registry across all modules, since the default promise registry is the same for all. However, if another dependency is using promise-registry, you may experience name conflicts. Fortunately, any string is valid as a key, so it is easy to "namespace" your promises, even without a custom registry.

app.js

const ui = require('./ui.js');
const login = require('./login.js');
const { once } = require('promise-registry');

// "my-app" namespace - you can do this however you want
const { username } = await once('my-app/user-logged-in');
ui.displaySplashScreen(username);

login.js

const auth = require('./auth.js');
const loginPromise = auth.loginWithCreds();
register('my-app/user-logged-in', loginPromise);

In this example, login.js will be loaded along with app.js and its code will be run synchronously. But even if that weren't the case (e.g. the dependency were lazy-loaded) it would still work fine - it doesn't matter whether register() or once() is called first.

Usage - Custom Registry

Using custom registries lets you create a registry specifically for a group of promises, making promise key naming conflicts less of an issue. However, it's on you to figure how to get the registry to the promise consumers and providers using e.g. dependency injection.

const promiseRegistry = require('promise-registry');

const config = require('./config.js');
const userInput = require('./user-input.js');
const display = require('./display.js');

// Example functions 
const callApi = async (url) => {
    return fetch(url).then(response => response.json())
}

const getRecords = async ([response, keysToGet]) => {
    let records = [];
    keysToGet.forEach(key => {
        const record = response[key];
        records[key] = record;
    });
    return records;
}

// Make a new registry
const initialization = promiseRegistry.makeRegistry();

// Register a new promise
initialization.register('api-response', callApi(config.getApiUrl()));

// Get a registered promise
const apiResponse = initialization.once('api-response');

// Get a promise that isn't registered yet
const keysToGet = initialization.once('user-selected-keys');

// Call once both above promises resolve
const recordsToShow = Promise.all([apiResponse, keysToGet]).then(getRecords);

// Register another new promise
initialization.register('records-to-show', recordsToShow);

// Register a promise by a name that's already depended on
initialization.register('user-selected-keys', userInput.selectResponseKeys());

// Call once all promises resolve
initialization.once('records-to-show').then(display.showRecords);

API

promiseRegistry.once(promiseName)

Get promise registered with promiseName. Can use before registration.

promiseRegistry.register(promiseName, promise)

Register promise with promiseName.

promiseRegistry.makeRegistry()

Create new registry with own once() and register() functions.