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

persevere-js

v1.5.0

Published

A utility that perseveres

Downloads

3,290

Readme

Description

A small utility that provides an easy-to-read syntax for awaiting on a condition to be satisfied. This makes testing asynchronous logic a breeze!

Heavily inspired by Awaitility which is a Java utility aimed at testing asynchronous systems.

Example

This utility could be used in both production and test code, but primarily use cases tend towards the latter.

For this example, imagine a simple backend for a local book store. The developer of the system wants to check the asynchronous 'real time' stocking system, which utilises a message queue. The flow for this is as follows:

  1. Customer purchases a book
  2. Purchase is placed onto a messaging queue for asynchronous processing
  3. The message is consumed at some point later (usually milliseconds, sometimes seconds, but never more than 10 seconds) later by the bookstore backend
  4. The books quantity is decremented by 1 in the database

The developer sets up the following simple test for this, thanks to PersevereJS 🚀

import { persevereFor } from "persevere-js";

describe('Stocking Tests', () => {
    it('should decrement stock quantity, when a book is purchased', async () => {
        // Given
        const book = new Book('Harry Potter and the Philosophers Stone')
        
        // When
        bookService.addPurchaseToQueue(book)
        
        // Then
        await persevereFor().atMost(10, 'SECONDS').until(() => bookRepository.getStockCountFor(book)).yieldsValue(0)
    })
})

In the above example, one of two things will happen:

  1. The stock count will become 0 for the book within the allotted 10-second period.
  2. The purchase message is never consumer, or takes longer than 10 seconds to be delivered and an exception will be thrown.

Usage

By chaining temporal bindings and until conditions, you can craft powerful mechanisms to wait for asynchronous conditions to satisfy.

The entrypoint into the wonderful world of waiting is the persevereFor function (note: persevere is also available and is functionally identical).

// Wait for at most 30 seconds, for there to be an order from bob in the databsse
await persevereFor()
    .atMost(30, 'SECONDS')
    .until(async () => {
        return db.query('SELECT ORDER_ID, CUSTOMER_ID FROM CUSTOMER_ORDERS');
    })
    .satisfies((customerOrders: { orderId: string, customerId: string}[]) => {
        return customerOrders
            .find(order => order.customerId = 'bob') != undefined;
    })

Temporal Bindings

You can utilise the following temporal bindings for your persevere functions:

  • atMost - Wait for at most the specified time for the condition to be met.
  • atLeast - Expect that at least the specified time has passed before the condition is met. (Note: Must also provide an upper temporal bound).

Until Conditions

You can utilise the following until conditions for determining success

  • yieldsValue - Stop waiting once the underlying promissory function yields the value specified.
  • satisfies - Stop waiting once the underlying promissory function satisfies the provided predicate.
  • noExceptions - Stop waiting as soon as the underlying promissory function resolves (doesn't reject/throw).

Licence

Copyright (c) 2023 James McNee Licensed under the MIT license.


This README was generated with ❤️ by readme-md-generator