diff --git a/src/allP.js b/src/allP.js index 9096f2229a..648e091cd7 100644 --- a/src/allP.js +++ b/src/allP.js @@ -1,6 +1,5 @@ import { bind } from 'ramda'; -/* eslint-disable max-len */ /** * Composable shortcut for `Promise.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; diff --git a/src/index.d.ts b/src/index.d.ts index d985f3161f..3d21be968e 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -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. */ @@ -777,6 +777,15 @@ declare namespace RamdaAdjunct { */ rejectP(value?: T): Promise; + /** + * 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(onFulfilled: Function, thenable: Promise): Promise; + thenP(onFulfilled: Function): (thenable: Promise) => Promise; + + /** * Runs the given list of functions in order with the supplied object, then returns the object. * Also known as the normal order sequencing combinator. diff --git a/src/index.js b/src/index.js index ceae93ea34..380e188846 100644 --- a/src/index.js +++ b/src/index.js @@ -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'; diff --git a/src/thenP.js b/src/thenP.js new file mode 100644 index 0000000000..635daedb69 --- /dev/null +++ b/src/thenP.js @@ -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; diff --git a/test/thenP.js b/test/thenP.js new file mode 100644 index 0000000000..f12942a69b --- /dev/null +++ b/test/thenP.js @@ -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); + }); +});