Welcome
Oath.js is a utility toolbelt for working with Promises in JavaScript. It can accept any Promises/A+-compliant promise object to any one of its methods.
Find out more about Oath in the Github repository. Contributions are welcome.
Documentation
Using Oath
Oath is simple enough to use. First, make sure Oath is installed:
npm install oathjs
From your JavaScript, you can include Oath by simple require()
ing it:
var oath = require('oathjs');
Arguments
Some methods, like all()
, accept only an array of promises. For any of these methods, either of the following two options are available:
- An array of promises is accepted as the first argument.
- An indefinite number of arguments are accepted, where each argument is a single promise.
all()
This method is a pass-through to the specced Promise.all()
method. It accepts an array of promises. If all of the promises resolve, this method will resolve with an array containing the fulfilled values of each of the promises. If any of the promises reject, this method will reject with the reason provided by the first promise to reject.
always()
This method accepts one argument:
prom
: A promise
When the passed promise resolves, this method will resolve with the passed promise's fulfilled value. When the passed promise rejects, this method will resolve with the passed promise's rejection reason.
any()
This method is the opposite of all()
. It accepts an array of promises. When any of the passed promises resolve, this method will resolve with the value provided by the passed promise. If all of the passed promises reject, this method will reject.
Note that this method is different from first()
in that it will not reject when the first passed promise rejects. Instead, it will only reject when all passed promises reject.
CancellablePromise()
var request = new oath.CancellablePromise(function(resolve, reject, cancelCallback) {
var xhr = require('xhr').get(url);
xhr.onload = resolve;
xhr.onerror = reject;
cancelCallback(xhr.abort, xhr); // Second argument is context
});
var timeout = setTimeout(request.cancel, 30000);
oath.always(request).then(clearTimeout.bind(null, timeout));
A cancellable promise is a promise that can be "turned off". It extends a normal promise, having identical behavior, except it has a cancel()
method. This method, when called, will cause the reject and resolve methods of the promise to noop.
Additionally, a third argument is passed to the promise's handler. This third argument is a function that can be called to set handlers for cancellation. When the promise is cancelled, each of the functions passed to the cancellation callback will be fired in the order that they were passed. An optional second argument can be provided for context.
Cancellable promises can only be cancelled a single time. If the promise is not pending, it cannot be cancelled.
filter()
filter()
accepts three arguments:
arr
: An array of promisesiterator
: A function to process the fulfilled value of each promise withcontext
: Optional value to pass as the context toiterator
After each of the promises passed in arr
resolves, the fulfilled value of each promise will be passed to iterator
. If iterator
returns false
for any input, the value returned by the corresponding promise will be excluded from the final fulfilled value of the method. When all passed promises have resolved, the method will resolve with an array containing all values which iterator
returned a truthy value for. The order of the values relative to their respective promises is preserved.
If any of the passed promises reject, the method will reject.
first()
oath.first(
pingHostname1(),
pingHostname2(),
pingHostname3()
).then(function(hostname) {
console.log(hostname + ' is the fastest');
}, function() {
console.warn('The connection may be flaky');
});
Aliased to race()
, as well.
This method accepts an array of promises. When any passed promise resolves or rejects, this method will resolve or reject with the same value or reason.
ignore()
setUpEnvironment().then(
// Ignore promises that reject
oath.ignore(
tryToRefreshEmail(),
updateRSSFeeds(),
downloadNewCalendarEvents()
)
).then(unlockUI);
This method accepts an array of promises. Rejected promises are ignored. When all passed promises have either resolved or rejected, this method will resolve with an array containing all fulfilled values of each of the passed promises that resolved. The relative ordering of the values is preserved.
map()
oath.map(
[getPublicPosts(), getPrivatePosts(), getFriendsPosts()],
function(posts) {
// This will be called immediately for each passed promise
// rather than after all promises have resolved.
return posts.postData;
}
).then(processAllPostData);
map()
accepts three arguments:
arr
: An array of promisesiterator
: A function to process the fulfilled value of each promise withcontext
: Optional value to pass as the context toiterator
If any of the passed promises reject, the method will reject with the passed promise's reason for rejection.
Functionally, map()
will behave in the following way:
Promise.all(arr).map(iterator, context);
The difference, however, is two-fold:
iterator
can return promises.map()
will processiterator
as soon as each of the passed promises resolve, resulting in improved performance.
The improved performance is due to the fact that the mapping process does not need to wait until all of the passed promises resolve. Instead, the fulfilled values are processed immediately and concurrently. This is especially true with asynchronous APIs.
rateLimit()
oath.rateLimit(2, [
uploadFile('favicon.ico'),
uploadFile('nope.gif'),
uploadFile('oh_snap.jpg'),
uploadFile('trololo.mp3')
]).then(function() {
console.log('upload complete');
});
rateLimit()
accepts three arguments:
limit
: The maximum number of simultaneously executing promisesarr
: An array of closures that return promisesrejectShouldAbort
: Boolean indicating whether a rejected promise should abort the process
When called, rateLimit
will shift closures from arr
until limit
has been reached. At that point, it will wait for the executing promises to resolve. When one or more of the promises resolve, the process of shifting closures will continue until all closures have been processed.
If any promise returned by a closure rejects, it will be ignored unless rejectShouldAbort
is truthy. If rejectShouldAbort
is truthy, the rejection reason of the rejected promise will be passed as the rejection reason for rateLimit
.