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

safe-promise-tools

v3.0.1

Published

Tools for working with Promises

Downloads

2

Readme

Differences from promise-tools

  • Updated to use typescript natively and generate the .js and .d.ts files
  • Fixed a small typing mistake that could only be caught with native Typescript or maybe 10x more tests
  • Switched to safe-timers instead of the native setTimeout, et al, functions

What is it?

There are a lot of nice Promise libraries out there like bluebird and q, with many handy functions that go above and beyond the small set of standard functions defined in the ECMAScript 2015 standard. But all of these libraries make you use their implementation of Promise (because all of them have been around since before Promises were part of the ECMAScript standard), and most of them are kind of on the big side (bluebird clocks in at almost 166k, unminified.)

The goal of safe-promise-tools is to provide a small library of async-like functions, and some other handy functions, and let you use these functions on top of any Promise implementation.

(Also, if you're writing a library and you want to make it easy for your callers to use either Promises or callbacks, be sure to check out promise-breaker).

Installation

npm install --save safe-promise-tools

Requirements

This library assumes that Promise is a defined global variable. If this is not the case on your platform, you can use a polyfill:

npm install --save es6-promise

Then somewhere in your node.js application:

require('es6-promise');

API

Collections

Utilities

Control Flow

Collections

map(arr, iterator, limit)

Calls iterator(item, index) for every item in map, which should return a Promise. If limit is specified, then at most limit calls to iterator will be started at a time (defaults to 1). Resolves to an array of items (the resolved value of each promise returned by iterator()). If any iterator rejects, this will reject immediately.

Utilities

defer()

Returns a {promise, resolve, reject} object. The returned promise will resolve or reject when resolve or reject are called.

Example:

var deferred = promiseTools.defer();
deferred.promise.then(function(result) {console.log(result);});
deferred.resolve("Hello world!");

delay(ms)

Returns a Promise which resolves after ms milliseconds have elapsed. The returned Promise will never reject.

Example:

console.log("start!");
promiseTools.delay(100)
.then(function() {console.log("end!");});

Control Flow

parallel(tasks, limit)

Alias: parallelLimit

Given an array of tasks, where each task is a function which takes no arguments and returns a Promise, executes each task in parallel (which is to say that all tasks will be started at once). If limit is supplied, then at most limit tasks will be started, and then as soon as any of these tasks complete a new task will be started to replace it.

Resolves to an array of equal length to tasks containing results returned by each task. If any task rejects, then this will reject immediately.

Example:

promiseTools.parallel([
    function() {return Promise.resolve("a");},
    function() {return "b";} // Note that raw return values are OK.
]).then(function(results) {
    // `results` will be ["a", "b"]
});

// Start 3 tasks, and then whenever a task completes will
// run another task, until all tasks are complete.
promiseTools.parallel(tasks, 3);

series(tasks)

Given an array of tasks, where each task is a function which takes no arguments and returns a Promise, executes each task one after another in series. A given task will not be started until the preceding task completes.

Resolves to an array of equal length to tasks containing results returned by each task. If any task rejects, then this will reject immediately.

Example:

promiseTools.series(
    function() {return Promise.resolve("a");}
    function() {return "b";} // Note that raw return values are OK.
).then(function(results) {
    // `results` will be ["a", "b"]
});

timeout(promise, ms)

Adds a timeout to an existing Promise.

Resolves to the same value as promise if promise resolves within ms milliseconds, otherwise the returned Promise will reject with the error "Timeout: Promise did not resolve within ${ms} milliseconds". The generated error will be an instance of promiseTools.TimeoutError.

Note that the underlying promise will continue to run, as there is no way to "cancel" a Promise in JavaScript.

Example:

// Will reject if `doSomething` takes longer than 500 milliseconds.
promiseTools.timeout(doSomething(), 500)
.then(...)

whilst(test, fn), doWhilst(fn, test)

While the synchronous function test() returns true, whilst will continuously execute fn(). fn() should return a Promise. whilst will resolve to the same value as the final call to fn(). If fn() or test() throw an error, then whilst() will reject immediately.

doWhilst() is similar to whilst(), but whilst() might execute fn() zero times if test() returns false on the first run, where doWhilst() is guaranteed to call fn() at least once. Note that the parameters are reversed between whilst() and doWhilst() to reflect the fact that one is "while /test/ do /fn/", and the other is "do /fn/ while /test/" (and to preserve API compatibility with async).

Example:

var count = 0;
promiseTools.whilst(
    () => count < 10, /* While count is less than 10... */
    function() {
        /* Do this... */
        count++;
        return Promise.resolve(count);
    }
)
.then(result => {
   // result will be 10 here.
});

retry(options, fn)

Will continuously call fn until it returns a synchronous value, doesn't throw, or returns a Promise that resolves. It will be retried options.times. You can pass {times: Infinity} to retry indefinitely. The fn will be passed the lastAttempt object which is the Error object of the last attempt.

Options: times (Default=5) and interval (Default=0). interval is the time between retries in milliseconds. If the options argument is passed as just a number, only times will be set.

Examples:

var count = 0;
promiseTools.retry({times: 4, interval: 5}, function(lastAttempt) {
    count++;
    if (count === 2) Promise.resolve(true);
    else Promise.reject(new Error('boom'));
})
.then(function(result) {
   // result will be `true` here.
});

---------------------------------------------

var count = 0;
promiseTools.retry(1, function(lastAttempt) {
    count++;
    if (count === 2) Promise.resolve(true);
    else Promise.reject(new Error('boom'));
})
.then(function(result) {
   // will not resolve.
})
.catch(function(err) {
    // err.message should be `boom` here.
});