-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0d8e15e
commit 0a61214
Showing
4 changed files
with
185 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* -------------------- | ||
* promise-methods module | ||
* `settle` method | ||
* ------------------*/ | ||
|
||
'use strict'; | ||
|
||
// Imports | ||
const isPromise = require('./is'), | ||
defer = require('./defer'); | ||
|
||
// Exports | ||
|
||
class Settler { | ||
constructor() { | ||
this.results = []; | ||
this.numAwaiting = 1; | ||
this.deferred = defer(); | ||
} | ||
|
||
run(promises) { | ||
let i = 0; | ||
for (const promise of promises) { | ||
const index = i; | ||
if (isPromise(promise)) { | ||
this.numAwaiting++; | ||
promise.then( | ||
res => this.resolved(index, res), | ||
err => this.rejected(index, err) | ||
); | ||
} else { | ||
this.results[index] = {resolved: true, result: promise}; | ||
} | ||
i++; | ||
} | ||
|
||
this.completed(); | ||
|
||
return this.deferred.promise; | ||
} | ||
|
||
resolved(index, result) { | ||
this.results[index] = {resolved: true, result}; | ||
this.completed(); | ||
} | ||
|
||
rejected(index, err) { | ||
this.results[index] = {resolved: false, result: err}; | ||
this.completed(); | ||
} | ||
|
||
completed() { | ||
this.numAwaiting--; | ||
if (this.numAwaiting === 0) this.deferred.resolve(this.results); | ||
} | ||
} | ||
|
||
/** | ||
* Waits for all promises in an array to settle (resolve or reject) and resolves to an array of | ||
* the results. | ||
* Each item in array is of form `{resolved: <boolean>, result: <any>}`. | ||
* `resolved` is `true` if promise resolved, `false` if rejected. | ||
* `result` is resolution value if resolved, rejection reason if rejected. | ||
* | ||
* @param {Array} promises - Array of promises | ||
* @returns {Promise} - Promise of array of results | ||
*/ | ||
module.exports = function settle(promises) { | ||
const awaiter = new Settler(); | ||
return awaiter.run(promises); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* -------------------- | ||
* promise-methods module | ||
* Tests for `settle` method | ||
* ------------------*/ | ||
|
||
'use strict'; | ||
|
||
// Modules | ||
const chai = require('chai'), | ||
chaiAsPromised = require('chai-as-promised'), | ||
{expect} = chai, | ||
{settle} = require('../index'); | ||
|
||
// Init | ||
chai.config.includeStack = true; | ||
chai.use(chaiAsPromised); | ||
|
||
// Tests | ||
|
||
describe('settle()', () => { | ||
it('resolves to array of result objects when all promise resolve', () => { | ||
const p = settle([Promise.resolve(123), Promise.resolve(456)]); | ||
return expect(p).to.eventually.deep.equal([ | ||
{resolved: true, result: 123}, | ||
{resolved: true, result: 456} | ||
]); | ||
}); | ||
|
||
it('awaits all promises', () => { | ||
const p1 = Promise.resolve(123); | ||
const p2 = new Promise( | ||
resolve => setTimeout(() => resolve(456), 50) | ||
); | ||
|
||
const p = settle([p1, p2]); | ||
return expect(p).to.eventually.deep.equal([ | ||
{resolved: true, result: 123}, | ||
{resolved: true, result: 456} | ||
]); | ||
}); | ||
|
||
it('returns rejection reason in results arr when a promise rejects', () => { | ||
const err = new Error('e'); | ||
const p = settle([Promise.resolve(123), Promise.reject(err)]); | ||
return expect(p).to.eventually.deep.equal([ | ||
{resolved: true, result: 123}, | ||
{resolved: false, result: err} | ||
]); | ||
}); | ||
|
||
it('returns rejection reasons in results arr when multiple promises reject', () => { | ||
const err1 = new Error('e1'), | ||
err2 = new Error('e2'); | ||
const p = settle([ | ||
Promise.resolve(123), | ||
Promise.reject(err1), | ||
Promise.reject(err2) | ||
]); | ||
|
||
return expect(p).to.eventually.deep.equal([ | ||
{resolved: true, result: 123}, | ||
{resolved: false, result: err1}, | ||
{resolved: false, result: err2} | ||
]); | ||
}); | ||
|
||
it('awaits all promises when one rejects', async () => { | ||
const err = new Error('e'); | ||
const p = settle([ | ||
Promise.reject(err), | ||
new Promise( | ||
resolve => setTimeout(() => resolve(123), 50) | ||
) | ||
]); | ||
|
||
return expect(p).to.eventually.deep.equal([ | ||
{resolved: false, result: err}, | ||
{resolved: true, result: 123} | ||
]); | ||
}); | ||
|
||
describe('with empty array', () => { | ||
it('promise resolves to empty array', () => { | ||
const p = settle([]); | ||
return expect(p).to.eventually.deep.equal([]); | ||
}); | ||
}); | ||
}); |