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 🙏

© 2025 – Pkg Stats / Ryan Hefner

redhawk

v0.0.3

Published

A promise library for Haxe, inspired by bluebird.js

Readme

redhawk

An experimental promise library for Haxe.

This library is mostly inspired by the Bluebird promise library for JavaScript. This library also attempts to conform to the Promises/A+ spec where possible. There are a few cases with a typed library where it is difficult to completely conform.

Table of Contents generated with DocToc

Installation

# Not published to lib.haxe.org (yet)
# Install using `haxelib dev ...` or `haxelib git ...`
$ haxelib git redhawk [email protected]:andywhite37/redhawk master src

Example

// Main.hx
package ;

import haxe.Timer;
import js.Error;
import redhawk.Promise;

class Main {
  public static function main() {
    trace("Starting!");

    new Promise(function(resolve, reject) {
      Timer.delay(function() {
        resolve("First value");
      }, 0);
    })

    // .then functions must return a promise
    .then(function(value) {
      trace(value);

      // Return a plain value (which will be coerced into a fulfilled promise)
      return "Second value";
    })

    .then(function(value) {
      trace(value);
      // Return a promise of a new value
      return new Promise(function(resolve, reject) {
        Timer.delay(function() {
          resolve("Third value");
        }, 0);
      });
    })

    .then(function(value) {
      trace(value);

      // Shortcut for creating a fulfilled promise
      return Promise.fulfilled("Fourth value");
    })

    .then(function(value) {
      trace(value);
      // Thrown exceptions are coerced into rejected promises
      throw new Error("something went wrong!");
    })

    // No rejection handler - the Error from above should propagate through
    // this then call.
    .then(function(value) {
      throw new Error('We should not have gotten here!');
    })

    // .end is like .then except that it cannot return a value nor promise.  This should
    // be used at the end of the promise chain, when you don't need/want to return a new value.
    // This is not like the `.done` method of libraries like Q.
    .end(function(value) {
      trace("Should not get here");
    }, function(reason) {
      trace('Oops: ${reason.value}');
    });

    // All then functions are invoked asynchronously
    trace("...just started");
  }
}

Build & run for Node.js:

$ haxe build.hxml

build.hxml file:

-lib redhawk
-main Main
-js main.js
-cmd node main.js

node main.js output:

Starting!
...just started
First value
Second value
Third value
Fourth value
Oops: Error: something went wrong!

Key concepts

The goal of this library was to leverage Haxe typing as much as possible while keeping the API as lightweight, easy, and non-verbose as possible. One key component in redhawk is the PromiseOrValue<T> abstract, which has implicit converters from Promise<T> and T, so that methods that return a PromiseOrValue<T> can simply return a raw Promise<T> or a T, and the library will coerce everything into a Promise<T>. Raw T values are coerced into fulfilled Promise<T>s. A similar abstract is used for rejection "reason" objects: Reason. At this time, the underlying rejection reason is a Dynamic for simplicity at the expense of type safety.

API Reference

PromiseOrValue<TValue>

An abstract type backed by an enum of either Promise<TValue> or TValue. Contains implicit conversions from Promise<TValue> and TValue and an implicit convert to Promise<TValue>.

Reason

An abstract type backed by a class that wraps a Dynamic value. The purpose of this class is to have a single rejection reason type, which allows for any value to be used as a rejection reason.

Promise<TValue>

The main Promise type for this library.

Promise construction

new Promise(?name, resolver)

Constructs a new Promise instance.

  • name: String- optional name for the Promise (for debugging)
  • resolver: ((TValue -> Void) -> (Reason -> Void) -> Void) - resolver function, e.g. function(resolve, reject) { /* resolve(value) or reject(reason) */ }
  • returns: Promise<TValue>

Example:

// Create a promise that is eventually fulfilled

var promise = new Promise(function(resolve, reject) {
  // Fulfill with a value
  resolve("some value");

  // Or asynchronously fulfill with a value
  Timer.delay(function() {
    resolve("This is the value!");
  }, 0);
});

// Create a Promise that is eventually rejected

var promise = new Promise(function(resolve, reject) {
  // Reject with any reason (value will be coerced into a `Reason` wrapper object)
  reject("My reason");

  // Or reject with an instance of any type (will be implicitly wrapped in a Reason object)
  reject(new js.Error("my error message"));
  reject(new MyError("my custom error"));
  reject(new MyClass("my custom error"));

  // Or throw an Error or other object.
  // The thrown object will be caught and turned into a rejected promise
  throw new Error("my error message");
  throw 'some string';

  // Or reject asynchronously
  Timer.delay(function() {
    reject('something went wrong');
  }, 0);
});
Promise.fulfilled(value)

Creates a new Promise that is fulfilled with the given value

  • value: TValue - value with which to fulfill the new Promise
  • returns: Promise<TValue> (fulfilled)

Shorthand for:

new Promise(function(resolve, reject) {
  resolve(value);
});
Promise.rejected(reason)

Creates a new Promise that is rejected with the given reason

  • reason: Reason - can pass any type, and it will implicitly converted to a Reason wrapper object
  • returns: Promise<TValue> (rejected)

Shorthand for:

new Promise(function(resolve, reject) {
  reject(reason);
});

Promise chaining

.then(?onFulfillment, ?onRejection)

Chains a fulfillment or rejection handler to this Promise When the previous promise is fulfilled or rejected, the corresponding .then fulfillment or rejection handler will be invoked on the "next tick."

  • onFulfillment: TValue -> PromiseOrValue<TValueNext> - optional fulfillment handler, which must return a Promise<TValueNext> or a TValueNext or throw.
  • onRejection: Reason -> PromiseOrValue<TValueNext>: optional rejection handler, which must return a Promise<TValueNext> or a TValueNext, or throw.
  • returns: Promise<TValueNext>

Example:

somePromise
  .then(function(value) {
    // Handle the value from somePromise...

    // return a new value (which will be converted to a Promise)
    return "another value";

    // Or return a promise
    return Promise.fulfilled("another value");
    return Promise.rejected("some error message");

    // Or throw any object (which will be converted to a rejected promise)
    throw new Error("some error");
  }, function(reason) {
    // Handle the reason - access the rejection/thrown object using `reason.value`
    trace('Something went wrong: ${reason.value}');

    // Return a new promise or value to send to the next chained handler
    return Promise.fulfilled("new value");

    // If the onRejection function is not provided, any rejections from
    // above promises will be propagated to the next handler.
  })
.end(?onFulfillment, ?onRejection)

Same as .then except that the onFulfillment and onRejection functions do not return a new Promise nor value. The promise chain ends with .end as it does not return a Promise, and no new asynchronous work should be started in the .end handlers.

Note: .end is not the same as the .done method of libraries like Q. In redhawk, unhandled errors are automatically thrown if unhandled after the next tick.

  • onFulfillment: TValue -> Void
  • onRejection: Reason -> Void
  • returns: Void

Example:

Promise.fulfilled("test1")
  .then(function(value) {
    // value == "test1"
    return "test2";
  })
  .end(function(value) {
    // value == "test2"
    // can't return promise/value now - chain is done
  }, function(reason) {
    trace('should not have gotten here');
    // can't return promise/value now - chain is done
  });
.catches(onRejection)

Chains a rejection handler which must return a new Promise<TValueNext> or TValueNext

  • onRejection: Reason -> PromiseOrValue<TValueNext>
  • returns: Promise<TValueNext>

Shorthand for:

.then(null, onRejection)`
.catchesEnd(onRejection)

Chains a rejection handler and ends the promise chain.

  • onRejection: Reason -> Void
  • returns: Void

Shorthand for:

.end(null, onRejection)
.finally(onFulfillmentOrRejection)

Chains a handler to invoke when the previous Promise is settled (either fulfilled or rejected). Finally can perform an async operation and return a Promise<Nil>, but if fulfilled, the previous Promise is returned.

  • onFulfillmentOrRejection: Void -> Void
  • returns: Promise<TValue> - the previous promise (which is fulfilled or rejected)

Conceptually similar to the following, except returns the previous prmoise when the handler settles:

.then(onFulfillmentOrRejection, onFulfillmentOrRejection)
.thenFulfilled(value)

Chains a handler that returns a new fulfilled Promise after the previous promise is fulfilled.

  • value: TValueNext

  • returns: Promise<TValueNext>

  • Shorthand for:

.then(function(_) {
  return Promise.fulfilled(value);
})
.thenRejected(reason)

Chains a handler that returns a new rejected Promise after the previous promise is fulfilled.

  • reason: Reason - previous promise rejection Reason
  • returns: Promise<TValueNext>

Shorthand for:

.catches(function(_) {
  return Promise.rejected(reason);
})
.tap(callback)

Invokes the callback for the fulfillment value of the previous promise then returns the previous promise.

  • callback: Void -> Void
  • returns: Promise<TValue>

Example:

somePromise
  .tap(function(value) {
    // Do something side-effecty with value
    trace(value);
  })
  .then(function(value) {
    // continue on with somePromise's value
  })
  ...
.delay(ms)

Adds a time delay to a promise chain

  • ms: Int - milliseconds to delay
  • returns: Promise<Nil>

Example:

somePromise
  .delay(500)
  .end(function(_) {
    // executed after 500ms delay
  });

Static helpers

Promise.tries(callback)

Executes a function and expects the return of a new Promise instance.

Intended to wrap blocks of synchronous code, so that throw exceptions can be turned into rejected Promises.

  • callback: Void -> PromiseOrValue<TValueNext>
  • returns: Promise<TValueNext>

Example:

Promise.tries(function() {
  // ...do something synchronous that might throw
  // If this throws, the error will be caught and returned as a rejected `Promise`

  // Return a `Promise`...
  return new Promise(function(resolve, reject) {
    // resolve or reject
  });
});
Promise.all(inputs)

Returns a Promise that is fulfilled when all the input Promises (or values) are fulfilled, or rejected if any input Promise is rejected. If fulfilled, the fulfillment value is an Array<Dynamic> of values corresponding to each input Promise. The input array can be a mix of Promises and values, and can be of mixed types.

  • inputs: Array<PromiseOrValue<Dynamic>>
  • returns: Promise<Array<Dynamic>>

Example:

Promise.all(["test1", Promise.fulfilled("test2"), "test3", 3, Promise.fulfilled(4)])
  .end(function(results) {
    // results : Array<Dynamic> == ["test1", "test2", "test3", 3, 4]
  }, function(reason) {
    trace("Something was rejected");
  });
Promise.any(inputs)

Returns a Promise that is fulfilled with the value of the first input promise that is fulfilled, or rejected if all input Promises are rejected.

  • inputs: Array<PromiseOrValue<Dynamic>>
  • returns: Promise<Dynamic>

Example:

Promise.any([Promise.rejected("test1"), "test2"])
  .end(function(result) {
    // result == "test2"
  });
Promise.many(inputs, manyCount)

Returns a Promise that is fulfilled with an array of manyCount values for the first manyCount input promises or values that are fulfilled, or rejected if fewer than manyCount input promises are fulfilled.

TODO: not sure if result array should have indices corresponding to input promises, or if it should be collapsed to remove nulls.

  • inputs: Array<PromiseOrValue<Dynamic>>
  • returns: Promise<Array<Dynamic>>

Example:

Promise.many([Promise.rejected("test1"), "test2", Promise.rejected("test3"), "test4", "test5"], 2)
  .end(function(results) {
    // results[1] == "test2" // TODO: or index 0?
    // results[3] == "test4" // TODO: or index 1?
  });
Promise.settled(inputs)

Returns a Promise that is fulfilled when all of the inputs are settled (fulfilled or rejected). The fulfillment value is an array of settled Promises which can be inspected using the Promise introspection methods.

  • inputs: Array<PromiseOrValue<Dynamic>>
  • returns: Array<Promise<Dynamic>>

Example:

Promise.settled(["test1", Promise.fulfilled(1), Promise.rejected(false)])
  .end(function(promises) {
    for (promise in promises) {
      if (promise.isFulfilled()) {
        trace(promise.getValue());
      } else if (promise.isRejected()) {
        trace(promise.getReason());
      }
    }
  });
Promise.map(inputs, mapper)

Maps an array of Promises or values of the same underlying type to an array of values of another type. Inputs are resolved before mapping, and the mapping function can be asynhronous (return a Promise).

  • inputs: Array<PromiseOrValue<TValueInput>>
  • mapper: TValueInput -> PromiseOrValue<TValueOutput>
  • returns: Promise<Array<TValueOutput>>

Example:

var inputs : Array<PromiseOrValue<Int> = [1, Promise.fulfilled(2), 3];

var mapper = function(input : Int) : PromiseOrValue<Int> {
  return Promise.delayed(50)
    .thenFulfilled(input * 2);
};

Promise.map(inputs, mapper)
  .end(function(results) {
    // results == [2, 4, 6]
  });
Promise.each(inputs, callback)

Iterates over an array of input Promises or values, and executes a side-effect callback for each resolved value. The callback can be asynchronous (return Promise<Nil>), but cannot change the input value. This method returns a Promise of an array of the resolved input values.

  • inputs: Array<PromiseOrValue<TValue>>
  • callback TValueInput -> PromiseOrValue
  • returns: Promise<Array<TValueInput>>

Example:

var inputs : Array<PromiseOrValue<Int> = [1, 2, 3];

var callback = function(input : Int) : PromiseOrValue<Int> {
  return Promise.delayed(function() {
    trace(input);
  }, 0);
};

Promise.each(inputs, callback)
  .end(function(results) {
    // each callback prints "1\n2\n3"
    // results == [1, 2, 3]
  });
Promise.reduce(inputs, reducer, initialValue)

Reduces an array of input Promises or values into a single value, using a potentially asynchronous reducer function.

  • inputs: Array<PromiseOrValue<TValueInput>>
  • reducer: TValueOutput -> TValueInput -> PromiseOrValue
  • initialValue: TValueOutput - the initial value of the reduction

Example:

var inputs : Array<PromiseOrValue<Int>> = [1, Promise.fulfilled(2), 3];

var reducer = function(acc : String, value : Int) : PromiseOrValue<String> {
  return Promise.delayed(50)
    .thenFulfilled(acc + Std.string(value));
};

var initialValue = "";

Promise.reduce(inputs, reducer, initialValue)
  .end(function(result) {
    // result == "123"
  });
Promise.filter(inputs, filterer)

Filters an array of input Promises or values using a potentially asynchronous filter function.

  • inputs: Array<PromiseOrValue<TValue>>
  • filterer: TValue -> PromiseOrValue<Bool>
  • returns: Promise<Array<TValue>> - filtered down using filterer

Example:

var inputs : Array<PromiseOrValue<Int>> = [1, 2, Promise.fulfilled(3), 4, 5];

var filterer = function(value : Int) : PromiseOrValue<Bool> {
  return Promise.delayed(50)
    .thenFulfilled(value < 4);
};

Promise.filter(inputs, filterer)
  .end(function(results) {
    // results = [1, 2, 3]
  });
Promise.delayed(ms)

Creates a promise that is fulfilled with Nil.nil after a ms time delay.

  • ms: Int - millisecond delay

Example:

Promise.delayed(500)
  .end(function(_) {
    // executed after 500ms delay
  });

Promise introspection

.isPending()

Indicates if a Promise is pending

  • returns: Bool
.isFulfilled()

Indicates if a Promise is fulfilled

  • returns: Bool
.isRejected()

Indicates if a Promise is rejected

  • returns: Bool
.isSettled()

Indicates if a Promise is settled (fulfilled or rejected)

  • returns: Bool
.getValue()

Gets the value of a fulfilled Promise

  • returns: TValue
.getReason()

Gets the reason of a rejected Promise

  • returns: Reason