Commit 795d6c12 authored by Mat Scales's avatar Mat Scales

Added an RSVP.all method, along with documentation and tests

parent 93baa87e
......@@ -10,7 +10,7 @@ It works in node and the browser. You can get the browser build in
## Promises
`RSVP.Promise` is an implementation of
`RSVP.Promise` is an implementation of
[Promises/A](http://wiki.commonjs.org/wiki/Promises/A) that passes the
[promises test suite](https://github.com/domenic/promise-tests) written
by Domenic Denicola.
......@@ -137,6 +137,27 @@ getJSON("/post/1.json").then(function(post) {
});
```
## Arrays of promises
Sometimes you might want to work with many promises at once. If you
pass an array of promises to the `all()` method it will return a new
promise that will be fulfilled when all of the promises in the array
have been fulfilled; or rejected immediately if any promise in the array
is rejected.
```javascript
var postIds = [2, 3, 5, 7, 11, 13];
var promises = [];
for(var i = 0; i < postIds.length; i++) {
promises.push(getJSON("/post/" + postIds[i] + ".json"));
}
RSVP.all(promises).then(function(posts) {
// posts contains an array of results for the given promises
});
```
## TaskJS
The [TaskJS](http://taskjs.org/) library makes it possible to take
......
......@@ -233,7 +233,33 @@ function reject(promise, value) {
});
}
function all(promises) {
var i, results = [];
var allPromise = new Promise();
var remaining = promises.length;
var resolver = function(index) {
return function(value) {
resolve(index, value);
};
};
var resolve = function(index, value) {
results[index] = value;
if (--remaining === 0) {
allPromise.resolve(results);
}
};
var reject = function(error) {
allPromise.reject(error);
};
for (i = 0; i < remaining; i++) {
promises[i].then(resolver(i), reject);
}
return allPromise;
}
EventTarget.mixin(Promise.prototype);
RSVP = { async: async, Promise: Promise, Event: Event, EventTarget: EventTarget };
RSVP = { async: async, Promise: Promise, Event: Event, EventTarget: EventTarget, all: all };
export = RSVP;
/*global RSVP, describe, specify, assert */
describe("RSVP extensions", function() {
describe("RSVP.all", function() {
specify('it should exist', function() {
assert(RSVP.all);
});
specify('fulfilled only after all of the other promises are fulfilled', function(done) {
var first = new RSVP.Promise();
var second = new RSVP.Promise();
setTimeout(function() {
first.resolve(true);
}, 0);
setTimeout(function() {
second.resolve(true);
}, 0);
RSVP.all([first, second]).then(function() {
assert(first.isResolved);
assert(second.isResolved);
done();
});
});
specify('rejected as soon as a promise is rejected', function(done) {
var first = new RSVP.Promise();
var second = new RSVP.Promise();
setTimeout(function() {
first.reject({});
}, 0);
setTimeout(function() {
second.resolve(true);
}, 5000);
RSVP.all([first, second]).then(function() {
assert(false);
}, function() {
assert(first.isRejected);
assert(!second.isResolved);
done();
});
});
specify('passes the resolved values of each promise to the callback in the correct order', function(done) {
var first = new RSVP.Promise();
var second = new RSVP.Promise();
var third = new RSVP.Promise();
third.resolve(3);
first.resolve(1);
second.resolve(2);
RSVP.all([first, second, third]).then(function(results) {
assert(results.length === 3);
assert(results[0] === 1);
assert(results[1] === 2);
assert(results[2] === 3);
done();
});
});
});
});
......@@ -28,6 +28,7 @@
<script src="../promises-tests/lib/tests/helpers/testThreeCases.js"></script>
<script>window.exports = undefined;</script>
<script>mocha.setup({ ui: 'bdd', timeout: 200 })</script>
<script src="extension-tests.js"></script>
<script src="../promises-tests/lib/tests/3.2.1.js"></script>
<script src="../promises-tests/lib/tests/3.2.2.js"></script>
<script src="../promises-tests/lib/tests/3.2.3.js"></script>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment