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

@peak-ai/event-dependent-promises

v1.0.7

Published

Proxy async methods to await prerequisite EventEmitter events

Downloads

11

Readme

Event-Dependent Promises

Verify

Proxy async methods to await prerequisite EventEmitter events:

import eventDependentPromises from '@peak-ai/event-dependent-promises';
import sdk, { Data, Events } from 'some-third-party-eventemitter';
import { APIGatewayEvent } from 'aws-lambda';

const dependentSdk = eventDependentPromises(
  sdk,
  Events.READY,
  Events.INIT_TIMEOUT,
  {
    getData(key: string) {
      // sdk.getData returns Promise<Data>
      return sdk.getData(key);
    },
  },
);

export const handler = (event: APIGatewayEvent): Promise<Data> => {
  const { body: key } = event;

  /* dependentSdk.getData(key) will invoke
   * and return sdk.getData(key) once the READY
   * event has been emitted or immediately
   * if it's been fired already. */
  return dependentSdk.getData(key);
};

Why?

If we wanted to, we could subscribe to our EventEmitter directly:

import sdk, { Data, Events } from 'some-third-party-eventemitter';
import { APIGatewayEvent, Context, Callback } from 'aws-lambda';
import keyService from './key-service';

let hasSdkInitialised = false;

export const handler = async (event: APIGatewayEvent, context: Context, cb: Callback<Data>): void => {
  const { body: id } = event;
  const key = await keyService.getForId(id);

  if (hasSdkInitialised) {
    const data = await sdk.getData(key);
    cb(null, data);
    return;
  }

  sdk.once(Events.READY, async () => {
    hasSdkInitialised = true;
    const data = await sdk.getData(key);
    cb(null, data);
  });
};

There are some key drawbacks, however, that present themselves:

  • Mixing multiple async paradigms (Promises and callbacks!)
  • Having to manually track whether the EventEmitter (sdk) has already fired its initialisation event (required for warm lambda invocations)

Event-Dependent Promises is directed a resolving (excuse the pun) these two issues by:

  • internally tracking when the prerequisite event has been emitted
  • proxying a set of methods to return Promises, which won't resolve until the prerequisite event has been fired once

Here's the previous example when using Event-Dependent Promises:

import eventDependentPromises from '@peak-ai/event-dependent-promises';
import sdk, { Data, Events } from 'some-third-party-eventemitter';
import { APIGatewayEvent } from 'aws-lambda';
import keyService from './key-service';

const dependentSdk = eventDependentPromises(
  sdk,
  Events.READY,
  Events.INIT_TIMEOUT,
  {
    getData(key: string) {
      // sdk.getData returns Promise<Data>
      return sdk.getData(key);
    },
  },
);

export const handler = async (event: APIGatewayEvent): Promise<Data> => {
  const { body: id } = event;
  const key = await keyService.getForId(id);

  /* Remember, dependentSdk.getData(key)
   * will wait for Events.READY to have
   * been emitted once before calling
   * and returning sdk.getData(key) */
  return dependentSdk.getData(key);
};

Getting started

You can install Event-Dependent Promises from npm:

npm i -E @peak-ai/event-dependent-promises

The library comprises of a single function, exposed via a default binding:

import eventDependentPromises from '@peak-ai/event-dependent-promises';

If you're using CommonJS, this means you'll have to destructure and rename the default binding:

const { default: eventDependentPromises } = require('@peak-ai/event-dependent-promises');

API

eventDependentPromises()

function eventDependentPromises<TSource extends EventEmitter, TMethods extends Methods>(
  eventSource: TSource,
  successEvent: string,
  failureEvent: string,
  methods: TMethods,
): TMethods

Arguments

  • eventSource: any EventEmitter
  • successEvent: the name of the event that suggests successful initialisation
  • failureEvent: the name of the event that suggests unsuccessful initialisation. If this is emitted, then the Promises returned by any of the methods will reject
  • methods: an object whose properties refer to async methods (i.e. returns a Promise or uses async/await) e.g:
const methods = {
  fetchItems() {
    return window.fetch('/items');
  },
};

Returns

TMethods

This is, on the surface, the same object you passed for the methods argument. However, each method is augmented to await the required event emission if it hasn't already occured.

Local development

Prerequisites:

  1. Fork this repo
  2. git clone <your fork>
  3. cd event-dependent-promises
  4. nvm i
  5. yarn

You can then run:

  • yarn lint: runs ESLint against the source code
  • yarn format:check: verifies that the source code adheres to our Prettier configuration
  • yarn format:write: fixes and overwrites any source files that don't adhere to our Prettier config
  • yarn build: runs the TypeScript compiler against the project and produces distributable output
  • yarn test: runs the unit tests

Contributing

Despite being primarily maintained by Peak, we welcome and appreciate any contributions from the community! Please see the contribution guidelines for more info.