Future

Models the eventual result of asynchronous computations.

This feature is experimental!

This API is still experimental, so it may change or be removed in future versions. You should not rely on it for production applications.

Documentation

Models the eventual result of asynchronous computations.

Static properties

Constructing

of(value)

Constructs a Future holding a successful value.

Experimental
rejected(reason)

Constructs a future holding a failure value.

Experimental

Converting from other types

fromPromise(aPromise)

Converts a Promise to a folktale Future.

Experimental

Fantasy Land

ap(that)

Part of the Applicative instance for Fantasy Land 1.x. See the apply method for details.

fantasy-land/ap(that)

Part of the Applicative instance for Fantasy Land 2.x+. See the apply method for details.

fantasy-land/of(value)

Part of the Applicative instance for Fantasy Land 2.x+. See the of method for details.

Special Values

prototype

A container for methods of Futures.

Instance (prototype) properties

Converting to other types

toPromise: value()

Converts a Future into a Promise.

Experimental

Debugging

inspect: value()

Returns a textual representation of the Future.

Experimental
toString: value()

Returns a textual representation of the Future.

Experimental

Fantasy Land

ap(that)

Part of the Applicative instance for Fantasy Land 1.x. See the apply method for details.

fantasy-land/ap(that)

Part of the Applicative instance for Fantasy Land 2.x+. See the apply method for details.

fantasy-land/bimap(f, g)

Part of the Bifunctor instance for Fantasy Land 2.x+. See the bimap method for details.

fantasy-land/chain(transformation)

Part of the Monad instance for Fantasy Land 2.x+. See the chain method for details.

fantasy-land/map(transformation)

Part of the Functor instance for Fantasy Land 2.x+. See the map method for details.

Internal Fields

get _listeners

A list of visitors to be invoked when the state of the future changes.

Abstract
get _state

The current state of the Future.

Abstract

Pattern Matching

willMatchWith: value(pattern)

Limited pattern matching for futures.

Experimental

Reacting to Futures

listen: value(pattern)

Adds a visitor to the Future, which will be invoked when the Future's state changes.

Experimental

Recovering From Errors

orElse: value(handler)

Transforms a failed future into a new future.

Experimental
recover: value(handler)

Transforms a failed future into a new future.

Deprecated
swap: value()

Inverts the state of a Future: successes become failures, failures become successes.

Experimental

Transforming

apply: value(future)

Transforms the succesful value of a future by using a function stored in another future.

Experimental
bimap: value(rejectionTransformation, successTransformation)

Transforms both successful and failure values in a Future, without touching its state.

Experimental
chain: value(transformation)

Transforms a Future's successful value along with its state.

Experimental
map: value(transformation)

Transforms the successful value of a Future, without touching its state.

Experimental
mapRejected: value(transformation)

Transforms failure values in a Future without touching its state.

Experimental

Types

constructor()

Models the eventual result of asynchronous computations.

Experimental

Source Code

Defined in source/concurrency/future/_future.js at line 24, column 0
class Future {
  constructor() {
    define(this, '_state', Pending());
    define(this, '_listeners', []);
  }


  // ---[ State and configuration ]------------------------------------
  /*~
   * isRequired: true
   * type: |
   *   get (Future 'f 's) => ExecutionState 'f 's
   */
  get _state() {
    throw new TypeError('Future.prototype._state should be implemented in an inherited object.');
  }

  /*~
   * isRequired: true
   * type: |
   *   get (Future 'f 's) => Array (DeferredListener 'f 's)
   */
  get _listeners() {
    throw new TypeError('Future.prototype._listeners should be implemented in an inherited object.');
  }


  // ---[ Reacting to Future events ]----------------------------------
  /*~
   * stability: experimental
   * type: |
   *   (Future 'f 's).(DeferredListener 'f 's) => Future 'f 's
   */
  listen(pattern) {
    this._state.matchWith({
      Pending:   ()           => this._listeners.push(pattern),
      Cancelled: ()           => pattern.onCancelled(), 
      Resolved:  ({ value })  => pattern.onResolved(value),
      Rejected:  ({ reason }) => pattern.onRejected(reason)
    });
    return this;
  }


  // --[ Transforming Futures ]----------------------------------------
  /*~
   * stability: experimental
   * type: |
   *   (Future 'f 's).(('s) => Future 's2) => Future 'f 's2
   */
  chain(transformation) {
    let deferred = new Deferred();    // eslint-disable-line prefer-const
    this.listen({
      onCancelled: ()     => deferred.cancel(),
      onRejected:  reason => deferred.reject(reason),
      onResolved:  value  => {
        transformation(value).listen({
          onCancelled: ()     => deferred.cancel(),
          onRejected:  reason => deferred.reject(reason),
          onResolved:  value2 => deferred.resolve(value2)
        });
      }
    });

    return deferred.future();
  }

  /*~
   * stability: experimental
   * type: |
   *   (Future 'f 's).(('s) => 's2) => Future 'f 's2
   */
  map(transformation) {
    return this.chain(value => Future.of(transformation(value)));
  }

  /*~
   * stability: experimental
   * type: |
   *   (Future 'f 's).(Future 'f (('s) => 's2)) => Future 'f 's2
   */
  apply(future) {
    return this.chain(fn => future.map(fn));
  }

  /*~
   * stability: experimental
   * type: |
   *   (Future 'f 's).(('f) => 'f2, ('s) => 's2) => Future 'f2 's2
   */
  bimap(rejectionTransformation, successTransformation) {
    let deferred = new Deferred();      // eslint-disable-line prefer-const
    this.listen({
      onCancelled: ()     => deferred.cancel(),
      onRejected:  reason => deferred.reject(rejectionTransformation(reason)),
      onResolved:  value  => deferred.resolve(successTransformation(value))
    });

    return deferred.future();
  }

  /*~
   * stability: experimental
   * type: |
   *   (Future 'f 's).(('f) => 'f2) => Future 'f2 's
   */
  mapRejected(transformation) {
    return this.bimap(transformation, x => x);
  }


  // ---[ Recovering from errors ]-------------------------------------
  /*~
   * deprecated:
   *   since: 2.1.0
   *   replacedBy: .orElse(handler)
   * 
   * type: |
   *   (Future 'f 's).(('f) => Future 'f2 's2) => Future 'f2 's
   */
  recover(handler) {
    warnDeprecation('`.recover` was renamed to `.orElse` for consistency, and thus `.recover(handler)` is deprecated. Use `.orElse(handler)` instead.');
    return this.orElse(handler);
  }

  /*~
   * stability: experimental
   * type: |
   *   (Future 'f 's).(('f) => Future 'f2 's2) => Future 'f2 's
   */
  orElse(handler) {
    let deferred = new Deferred();      // eslint-disable-line prefer-const
    this.listen({
      onCancelled: ()     => deferred.cancel(),
      onResolved:  value  => deferred.resolve(value),
      onRejected:  reason => {
        handler(reason).listen({
          onCancelled: ()        => deferred.cancel(),
          onResolved:  value     => deferred.resolve(value),
          onRejected:  newReason => deferred.reject(newReason)
        });
      }
    });

    return deferred.future();
  }


  /*~
   * stability: experimental
   * type: |
   *   forall a, b, c, d:
   *     type Pattern = { r |
   *       Cancelled: ()  => Future c d,
   *       Resolved:  (b) => Future c d,
   *       Rejected:  (a) => Future c d
   *     }
   *     
   *     (Future a b).(Pattern) => Future c d 
   */
  willMatchWith(pattern) {
    let deferred = new Deferred();      // eslint-disable-line prefer-const
    const resolve = (handler) => (value) => handler(value).listen({
      onCancelled: ()         => deferred.cancel(),
      onResolved:  (newValue) => deferred.resolve(newValue),
      onRejected:  (reason)   => deferred.reject(reason) 
    });
    this.listen({
      onCancelled: resolve(pattern.Cancelled),
      onResolved:  resolve(pattern.Resolved),
      onRejected:  resolve(pattern.Rejected)
    });

    return deferred.future();
  }

  /*~
   * stability: experimental
   * type: |
   *   (Future 'f 's).() => Future 's 'f
   */
  swap() {
    let deferred = new Deferred();    // eslint-disable-line prefer-const
    this.listen({
      onCancelled: ()     => deferred.cancel(),
      onRejected:  reason => deferred.resolve(reason),
      onResolved:  value  => deferred.reject(value) 
    });

    return deferred.future();
  }


  // ---[ Debugging ]--------------------------------------------------
  /*~
   * stability: experimental
   * type: |
   *   (Future 'f 's).() => String
   */
  toString() {
    const listeners = this._listeners.length;
    const state     = this._state;

    return `folktale:Future(${state}, ${listeners} listeners)`;
  }

  /*~
   * stability: experimental
   * type: |
   *   (Future 'f 's).() => String
   */
  inspect() {
    return this.toString();
  }


  /*~
   * stability: experimental
   * type: |
   *   forall e, v:
   *     (Future e v).() => Promise v e
   */
  toPromise() {
    return require('folktale/conversions/future-to-promise')(this);
  }
}
Stability
experimental
Licence
MIT
Module
folktale/concurrency/future/_future
Authors
Copyright
(c) 2013-2017 Quildreen Motta, and CONTRIBUTORS
Authors
  • Quildreen Motta
Maintainers
  • Quildreen Motta <queen@robotlolita.me> (http://robotlolita.me/)