Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

pacta

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pacta

An algebraic, Promises/A+ compliant implementation of Promises.

  • 0.2.0
  • Source
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

pacta Build Status

{ 'pacta': '0.2.0' }

This is an implementation of algebraic, Promises/A+ compliant Promises in node.js.

Promises can be thought of as objects representing a value that may not have been calculated yet (they are sometimes referred to as Deferreds).

An obvious example is the result of an asynchronous HTTP request: it's not clear when the request will be fulfilled but it will be at some point in the future. Having actual Promise objects representing these eventual values allows you to compose, transform and act on them without worrying about their time or sequence of execution.

At their most basic, an empty promise can be created and resolved like so:

var Promise = require('pacta').Promise;

var p = new Promise();
setTimeout(function () {

  /* Populate the promise with its final value. */
  p.resolve(1);
}, 1000);

Promises can also be marked as rejected (viz. represent an error state) like so:

/* Mark the promise as rejected with a reason. */
p.reject('The server could not be found.');

Concretely, a promise can be represented by the following deterministic finite automaton:

For a worked example of using promises, see the two example programs and sample HTTP client included in Pacta.

Pacta's promises can be used as the following algebraic structures as defined in the Fantasy Land Specification:

Pacta's promises are compliant with the Promises/A+ specification, providing a then method.

Promises are resolved (or fulfilled) with Promise#resolve and rejected with Promise#reject.

To execute code on rejection without using Promise#then, use Promise#onRejected.

Pacta also provides the following functions for creating and working with Promises of lists:

  • Promise#conjoin to concatenate promises into a list of values regardless of their original type meaning that non-Monoid types can be combined with others (e.g. a promise of 'foo' can be conjoined with [1, 2] to produce ['foo', 1, 2]);
  • Promise#append to append promises to an initial promise of a list. This means that you can work more easily with multiple promises of lists without joining them together (as would be done with concat and conjoin), e.g. appending a promise of [2, 3] to a promise of [1] results in [1, [2, 3]] rather than [1, 2, 3]);
  • Promise#reduce to reduce a list within a promise;
  • Promise#spread to map over a promise's value but, instead of receiving a single value, spread the promise's value across separate arguments:
Promise.of([1, 2]).spread(function (x, y) {
  console.log(x); //=> 1
  console.log(y); //=> 2
});

It also defines a monoid interface for Array and String, implementing empty such that:

Array.empty();  //=> []
String.empty(); //=> ""

See the test suite for more information.

Usage

var Promise = require('pacta').Promise;

var p = new Promise();
setTimeout(function () {
  p.resolve('Foo');
}, 1000);

p.map(console.log); //=> "Foo"

p.map(function (x) {
  return x + '!';
}).map(console.log); //=> "Foo!"

var p2 = new Promise();
setTimeout(function () {
  p2.resolve(['bar']);
}, 500);

var p3 = Promise.of(['baz']);

p2.concat(p3).map(console.log); //=> [ 'bar', 'baz' ]

p.conjoin(p2).map(console.log); //=> [ 'Foo', 'bar' ]

Promise.of([]).append(p).append(p2).map(console.log);
//=> [ 'Foo', [ 'bar' ] ]

p2.append(p).spread(function (x, y) {
  console.log(x); //=> 'bar'
  console.log(y); //=> 'Foo'
});

var p4 = new Promise();
setTimeout(function () {
  p4.reject('Error!');
}, 1000);

p4.onRejected(function (reason) {
  console.error('Failed due to', reason);
}); //=> Failed due to Error!

p4.then(function (value) {
  console.log('Success!', value);
}, function (reason) {
  console.error('Failure!', reason);
}); //=> Failure! Error!

API Documentation

Promise()

var promise = new Promise();

Create a new, unfulfilled promise that will eventually be populated with a value (through resolve).

Promise.of(x)

var promise = Promise.of(1);
var promise = Promise.of('foo');

Create a new, fulfilled promise already populated with a value x.

Promise#resolve(x)

var promise = new Promise();
promise.resolve(5);

Populate a promise with the value x thereby resolving it.

This function can also be called as Promise#fulfill.

Promise#reject(reason)

var promise = new Promise();
promise.reject('Errored out!');

Mark a promise as rejected, populating it with a reason.

Promise#map(f)

var promise = Promise.of(2);

promise.map(function (x) {
  console.log(x);

  return x * 2;
}); //=> Promise.of(4)

promise.map(function (x) {
  return Promise.of(x * 2);
}); //=> Promise.of(Promise.of(4))

Execute a function f on the contents of the promise. This returns a new promise containing the result of applying f to the initial promise's value.

In Haskell notation, its type signature is:

map :: Promise a -> (a -> b) -> Promise b

Note that this is the primary way of acting on the value of a promise: you can use side-effects within your given function (e.g. console.log) as well as modifying the value and returning it in order to affect the returning promise.

### Promise#then([onFulfilled[, onRejected]])

promise.then(function (value) {
  return x * 2;
}); //=> Promise.of(4)

promise.then(function (value) {
  return Promise.of(x * 2);
}); //=> Promise.of(4)

promise.then(function (value) {
  console.log('Success!', value);
}, function (reason) {
  console.error('Error!', reason);
});

An implementation of the Promises/A+ then method, taking an optional onFulfilled and onRejected function to call when the promise is fulfilled or rejected respectively.

Like Promise#map, then returns a promise itself and can be chained.

Promise#onRejected(f)

var p = new Promise();
p.reject('Error!');
p.onRejected(function (reason) {
  console.error('Failed:', reason);
});

Identical to Promise#map but only executed when a promise is rejected rather than resolved.

Promise#concat(p)

var promise = Promise.of('foo'),
    promise2 = Promise.of('bar');

promise.concat(promise2); //=> Promise.of('foobar')

Concatenate the promise with another promise p into one containing both values concatenated together. This will work for any promise containing a semigroup (viz. a value that supports concat) such as String or Array. Note that concat's usual behaviour of joining arrays, etc. applies.

Its type signature is:

concat :: Promise a -> Promise a -> Promise a

If either of the original two promises is rejected, the resulting concatenated promise will also be rejected. Note that only the first rejection will count as further rejections will be ignored.

See also Promise#conjoin and Promise#append.

Promise#chain(f)

var promise = Promise.of(2);

promise.chain(function (x) { return Promise.of(x * 2); }); //=> Promise.of(4)

Execute a function f with the value of the promise. This differs from Promise#map in that the function must return a promise itself.

Its type signature is:

chain :: Promise a -> (a -> Promise b) -> Promise b

Promise#ap(p)

var promise = Promise.of(function (x) { return x * 2; }),
    promise2 = Promise.of(2);

promise.ap(promise2); //=> Promise.of(4)

On a promise containing a function, call that function with a promise p containing a value.

Its type signature is:

ap :: Promise (a -> b) -> Promise a -> Promise b

Promise#empty()

var promise = Promise.of('woo');

promise.empty(); //=> Promise.of('')

On a promise containing a monoid (viz. something with an empty() function on itself or its constructor like Array or String), return a new promise with an empty version of the initial value.

(Pacta ships with Monoid implementations for Array and String by default.)

Promise#conjoin(p)

var promise = Promise.of(1),
    promise2 = Promise.of([2, 3]);

promise.conjoin(promise2); //=> Promise.of([1, 2, 3])

Conjoin the promise with another promise p, converting their values to arrays if needed (e.g. 'foo' into ['foo']). This differs from Promise#concat which only works on promises of values that are semigroups themselves.

All values are coerced to arrays using [].concat.

Promise#append(p)

var promise = Promise.of([]),
    promise2 = Promise.of([1]);

promise.append(promise2); //=> Promise.of([[1]])

On a promise of a list, append another promise p's value to it without joining (e.g. appending [1] to [] results in [[1]]).

This is particularly useful when dealing with several promises containing lists and you want to keep them separated instead of being merged into one as would happen with Promise#concat and Promise#conjoin.

Promise#reduce(f[, initialValue])

var promise = Promise.of([1, 2, 3]);

promise.reduce(function (acc, e) {
  return acc + e;
}, 0); //=> Promise.of(6)

On a promise containing an array, reduce its value, returning a promise of the resulting value. This defers to the underlying signature of reduce taking a function f and an optional initialValue.

Promise#spread(f)

var promise = Promise.of([1, 2]);

promise.spread(function (x, y) {
  return x + y;
}); //=> Promise.of(3)

Similar to Promise#map, apply a function f to a promise of a list but, instead of receiving a single argument, pass each value of the list to the function separately.

Acknowledgements

James Coglan and Aanand Prasad convinced me to explore the idea of monadic promises and Brian McKenna's "Fantasy Land" specification and feedback were essential.

Fantasy Land Promises/A+

License

Copyright © 2013 Paul Mucur.

Distributed under the MIT License.

Keywords

FAQs

Package last updated on 20 Jun 2013

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc