Skip to content

Commit

Permalink
feat: add thenP (#551)
Browse files Browse the repository at this point in the history
Ref #35
  • Loading branch information
char0n authored May 13, 2018
1 parent 47d4560 commit 92ba7b5
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 3 deletions.
2 changes: 0 additions & 2 deletions src/allP.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { bind } from 'ramda';

/* eslint-disable max-len */
/**
* Composable shortcut for `Promise.all`.
*
Expand All @@ -24,7 +23,6 @@ import { bind } from 'ramda';
* RA.allP([Promise.resolve(1), Promise.resolve(2)]); //=> Promise([1, 2])
* RA.allP([1, Promise.reject(2)]); //=> Promise(2)
*/
/* eslint-enable */
const allP = bind(Promise.all, Promise);

export default allP;
11 changes: 10 additions & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ declare namespace RamdaAdjunct {
(high: number, value: number): boolean;
(high: number): (value: number) => boolean;
};

/**
* Returns whether or not an object has an own property with the specified name at a given path.
*/
Expand Down Expand Up @@ -777,6 +777,15 @@ declare namespace RamdaAdjunct {
*/
rejectP<T>(value?: T): Promise<T>;

/**
* Composable shortcut for `Promise.then`.
* The thenP function returns a Promise. It takes two arguments: a callback function for the success of the Promise
* and the promise instance itself.
*/
thenP<T>(onFulfilled: Function, thenable: Promise<T>): Promise<T>;
thenP<T>(onFulfilled: Function): (thenable: Promise<T>) => Promise<T>;


/**
* Runs the given list of functions in order with the supplied object, then returns the object.
* Also known as the normal order sequencing combinator.
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export { default as curryRight } from './curryRight';
export { default as allP } from './allP';
export { default as resolveP } from './resolveP';
export { default as rejectP } from './rejectP';
export { default as thenP } from './thenP';
export { default as Y } from './Y';
export { default as seq } from './seq';
export { default as sequencing } from './seq';
Expand Down
27 changes: 27 additions & 0 deletions src/thenP.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { invoker } from 'ramda';

/**
* Composable shortcut for `Promise.then`.
* The thenP function returns a Promise. It takes two arguments: a callback function for the success of the Promise
* and the promise instance itself.
*
* @func thenP
* @memberOf RA
* @since {@link https://char0n.github.io/ramda-adjunct/2.8.0|v2.8.0}
* @category Function
* @sig (a -> Promise b | b) -> Promise b
* @param {Function} onFulfilled A Function called if the Promise is fulfilled. This function has one argument, the fulfillment value
* @param {Promise} promise Any Promise or Thenable object
* @return {Promise} A Promise in the pending status
* @see {@link RA.resolveP|resolveP}, {@link RA.rejectP|rejectP}, {@link RA.allP|allP}
* @example
*
* const promise = Promise.resolve(1);
* const add1 = v => v + 1;
*
* RA.thenP(add1, promise); // => Promise(2)
*/
const thenP = invoker(1, 'then');

export default thenP;
51 changes: 51 additions & 0 deletions test/thenP.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { assert } from 'chai';
import sinon from 'sinon';
import * as R from 'ramda';

import * as RA from '../src/index';

describe('thenP', function() {
context('when applied on Promise', function() {
specify('should call then method with onFulfilled function', function() {
const promise = RA.resolveP(1);
const expected = RA.thenP(R.add(1), promise);

assert.eventually.strictEqual(expected, 2);
});
});

context('when applied on Thenable', function() {
specify('should call then method with onFulfilled function', function() {
const thenable = { then: fn => RA.resolveP(fn(1)) };
const expected = RA.thenP(R.add(1), thenable);

assert.eventually.strictEqual(expected, 2);
});
});

context('when applied on non-thenable', function() {
specify('should throw TypeError', function() {
assert.throws(() => RA.thenP(R.identity, {}), TypeError);
});
});

it('should call `then` method on thenable', function(done) {
const then = sinon.stub().returns(RA.resolveP(1));
const thenable = { then };
const expected = RA.thenP(R.identity, thenable);

expected.then(() => {
assert.isTrue(then.calledOnce);
done();
});
});

it('should have arity of 2', function() {
assert.strictEqual(RA.thenP.length, 2);
});

it('should be curried', function() {
assert.eventually.strictEqual(RA.thenP(R.identity, RA.resolveP(1)), 1);
assert.eventually.strictEqual(RA.thenP(R.identity)(RA.resolveP(1)), 1);
});
});

0 comments on commit 92ba7b5

Please sign in to comment.