0.1.0 • Published 8 years ago

promise-delegates v0.1.0

Weekly downloads
2
License
MIT
Repository
github
Last release
8 years ago

promise-delegates Build Status Coverage Status

Extend the promise API with methods and accessors that delegate to the future value.

If you have ever used delegates, this API will feel very familiar. If you haven't, you probably should at least read their documentation to understand the basic concept. This library is very similar, but operates on promises.

Install

$ npm install --save promise-delegates

Usage

const delegate = require('promise-delegates');

let config = delegate()
  .method('foo')
  .getter('bar');

let somePromise = config.apply(promiseFn());
    
// the args are stored and the method is executed on the promise result.    
somePromise.foo('args...'); 
 
// returns a promise for the `bar` property on the resolved value of `somePromise`. 
somePromise.bar;   

API Summary

Most methods have very similar signatures. Unless otherwise noted, every method is chainable (returns config itself). More detailed explanations and examples are below.

  • config.apply(promiseInstance) - Extends a single promise instance. Returns promiseInstance

  • config.wrap(promiseFn) - Returns a wrapped version of promiseFn that will extend every returned promise as defined in config.

  • config.getter(propertyName, [childConfig]) - Define a getter that returns a promise for a member of the resolved value.

  • config.setter(propertyName) - Define a setter. Setters can not specify a return value, so a promise is not returned.

  • config.access(propertyName, [childConfig]) - Define a getter and setter. childConfig only applies to the getter.

  • config.method(methodName, [childConfig]) - Store the args, and call the method on the resolved value.

  • config.chain(methodName) - Same as config.method, but returns the `basePromise for chaining. Useful if your promise resolves to an object that itself has chainable functions (i.e. a promise for an EventEmitter).

Child Configs and Chaining

Child configs become very helpful in allowing you to build expressive chainable API's'.

Let's pretend we have an entirely async class called Person, with the following members:

  • mother - A property containing a promise for the persons mother.
  • father - A property containing a promise for the persons father.
  • child(n) - A method that returns a promise for the persons nth child.

Now let's define a config to wrap a promise for Person:

let personConfig = delegate();

personConfig
  .getter('mother', personConfig)
  .getter('father', personConfig)
  .method('child', personConfig)

Assuming getPerson(name) returns a promise for a Person, we can do the following:

// wrap the promising returning function.
getPerson = personConfig.wrap(getPerson);

// let's fetch my mothers, fathers, first born
var auntSharon = getPerson('James').mother.father.child(1);

That last line is equivalent to the following:

var auntSharon = getPerson('James')
  .then(function (me) {
    return me.mother;
  })
  .then(function (mother) {
    return mother.father;
  })
  .then(function (grandpa) {
    return grandpa.child(1);
  });  

API

delegate()

Creates a new delegateConfig instance for defining a set of extensions to a promise.

delegateConfig.apply(basePromise)

Returns: basePromise

Applies the config built using the methods below basePromise. basePromise will be extended with the property accessors and methods defined in the config.

delegateConfig.wrap(promiseFn, ctx)

Returns: wrappedFn - a wrapped function.

Wrap a promise returning function. All promises returned from wrappedFn will be extended using config. The optional ctx command can be used to bind the this value that is used when calling promiseFn.

delegateConfig.getter(propertyName, childConfig)

Chainable

Defines a property getter on the basePromise. The value returned by the getter is a promise for a property on the resolved value of basePromise.

delegate().getter('foo').apply(somePromise);

let foo = somePromise.foo; 

is equivalent to:

let foo = somePromise.then(function (result) {
  return result.foo;
});
propertyName

Type: string

The property name for the getter created.

childConfig

Type: delegateConfig

If supplied, the promise returned from the getter will be extended with this config.

delegateConfig.setter(propertyName)

Chainable

Defines a property setter on the basePromise. Setters can not specify return a value.

delegate().setter('foo').apply(somePromise);

somePromise.foo = 'bar'; 

is equivalent to:

somePromise.then(function (result) {
  result.foo = 'bar';
});

delegateConfig.access(propertyName, childConfig)

Chainable

Defines a getter and setter on the basePromise. childConfig only applies to the getter.

delegateConfig.method(propertyName, childConfig)

Chainable

Defines a method on the basePromise. When invoked, the method will store its arguments and perform the same invocation on the resolved value of basePromise. The returned value is a promise for the result of the method invocation. The returned value can optionally be extended with childConfig.

delegate().method('foo').apply(somePromise);

let foo = somePromise.foo('bar', 'baz'); 

is equivalent to:

let foo = somePromise.then(function (result) {
  return result.foo('bar', 'baz');
});

delegateConfig.chain(propertyName)

Chainable

Defines a method on the basePromise. When invoked, the method will store its arguments and perform the same invocation on the resolved value of basePromise. The returned value is basePromise. This is useful if the promises resolved value has chainable methods (methods that return the invocation target).

// assume promiseFn returns promises that resolve to an eventEmitters
promiseFn = delegate().chain('on').wrap(promiseFn);

promiseFn('foo')
  .on('some-event', ...)
  .on('other-event', ...)
  .then(...) 

License

MIT © James Talmage