[Pkg-javascript-commits] [node-q] 01/05: Imported Upstream version 1.2.0
Sebastiaan Couwenberg
sebastic at moszumanska.debian.org
Sat Apr 25 10:08:09 UTC 2015
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository node-q.
commit b720253bae8e430b835c8ad4776d77144972e0e1
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Sat Apr 25 11:56:21 2015 +0200
Imported Upstream version 1.2.0
---
CHANGES.md | 10 ++-
README.md | 14 +++-
package.json | 2 +-
q.js | 59 +++++++++++++--
spec/q-spec.js | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 297 insertions(+), 13 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 5d9eca7..b138b13 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,12 @@
<!-- vim:ts=4:sts=4:sw=4:et:tw=70 -->
+## 1.2.0
+
+ - Added Q.any(promisesArray) method (@vergara).
+ Returns a promise fulfilled with the value of the first resolved promise in
+ promisesArray. If all promises in promisesArray are rejected, it returns
+ a rejected promise.
+
## 1.1.2
- Removed extraneous files from the npm package by using the "files"
@@ -109,7 +116,7 @@ have been distributed far and wide and demand long term support.
## 0.9.4
- - `isPromise` and `isPromiseAlike` now always returns a boolean
+ - `isPromise` and `isPromiseAlike` now always returns a boolean
(even for falsy values). #284 @lfac-pt
- Support for ES6 Generators in `async` #288 @andywingo
- Clear duplicate promise rejections from dispatch methods #238 @SLaks
@@ -759,4 +766,3 @@ Their replacements are listed here:
## 0.0.1
- initial version
-
diff --git a/README.md b/README.md
index b10ea04..9065bfa 100644
--- a/README.md
+++ b/README.md
@@ -335,6 +335,18 @@ Q.allSettled(promises)
});
```
+The ``any`` function accepts an array of promises and returns a promise that is
+fulfilled by the first given promise to be fulfilled, or rejected if all of the
+given promises are rejected.
+
+```javascript
+Q.any(promises)
+.then(function (first) {
+ // Any of the promises was fulfilled.
+}, function (error) {
+ // All of the promises were rejected.
+});
+```
### Sequences
@@ -864,6 +876,6 @@ You can view the results of the Q test suite [in your browser][tests]!
## License
-Copyright 2009–2014 Kristopher Michael Kowal
+Copyright 2009–2015 Kristopher Michael Kowal and contributors
MIT License (enclosed)
diff --git a/package.json b/package.json
index fa99c9e..9df9c50 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "q",
- "version": "1.1.2",
+ "version": "1.2.0",
"description": "A library for promises (CommonJS/Promises/A,B,D)",
"homepage": "https://github.com/kriskowal/q",
"author": "Kris Kowal <kris at cixar.com> (https://github.com/kriskowal)",
diff --git a/q.js b/q.js
index 49e945a..d9405fd 100644
--- a/q.js
+++ b/q.js
@@ -59,7 +59,7 @@
self.Q = definition();
} else {
- throw new Error("This environment was not anticiapted by Q. Please file a bug.");
+ throw new Error("This environment was not anticipated by Q. Please file a bug.");
}
})(function () {
@@ -1502,7 +1502,7 @@ Promise.prototype.keys = function () {
Q.all = all;
function all(promises) {
return when(promises, function (promises) {
- var countDown = 0;
+ var pendingCount = 0;
var deferred = defer();
array_reduce(promises, function (undefined, promise, index) {
var snapshot;
@@ -1512,12 +1512,12 @@ function all(promises) {
) {
promises[index] = snapshot.value;
} else {
- ++countDown;
+ ++pendingCount;
when(
promise,
function (value) {
promises[index] = value;
- if (--countDown === 0) {
+ if (--pendingCount === 0) {
deferred.resolve(promises);
}
},
@@ -1528,7 +1528,7 @@ function all(promises) {
);
}
}, void 0);
- if (countDown === 0) {
+ if (pendingCount === 0) {
deferred.resolve(promises);
}
return deferred.promise;
@@ -1540,6 +1540,55 @@ Promise.prototype.all = function () {
};
/**
+ * Returns the first resolved promise of an array. Prior rejected promises are
+ * ignored. Rejects only if all promises are rejected.
+ * @param {Array*} an array containing values or promises for values
+ * @returns a promise fulfilled with the value of the first resolved promise,
+ * or a rejected promise if all promises are rejected.
+ */
+Q.any = any;
+
+function any(promises) {
+ if (promises.length === 0) {
+ return Q.resolve();
+ }
+
+ var deferred = Q.defer();
+ var pendingCount = 0;
+ array_reduce(promises, function(prev, current, index) {
+ var promise = promises[index];
+
+ pendingCount++;
+
+ when(promise, onFulfilled, onRejected, onProgress);
+ function onFulfilled(result) {
+ deferred.resolve(result);
+ }
+ function onRejected() {
+ pendingCount--;
+ if (pendingCount === 0) {
+ deferred.reject(new Error(
+ "Can't get fulfillment value from any promise, all " +
+ "promises were rejected."
+ ));
+ }
+ }
+ function onProgress(progress) {
+ deferred.notify({
+ index: index,
+ value: progress
+ });
+ }
+ }, undefined);
+
+ return deferred.promise;
+}
+
+Promise.prototype.any = function() {
+ return any(this);
+};
+
+/**
* Waits for all promises to be settled, either fulfilled or
* rejected. This is distinct from `all` since that would stop
* waiting at the first rejection. The promise returned by
diff --git a/spec/q-spec.js b/spec/q-spec.js
index 005e3cb..f1d726e 100644
--- a/spec/q-spec.js
+++ b/spec/q-spec.js
@@ -196,9 +196,9 @@ describe("always next tick", function () {
spyOn(Q, 'nextTick').andCallFake(function immediateTick(task){
task();
});
-
+
Q.when(Q(), spy);
-
+
expect(spy).toHaveBeenCalled();
expect(Q.nextTick).toHaveBeenCalled();
});
@@ -1183,6 +1183,223 @@ describe("all", function () {
});
+describe("any", function() {
+ it("fulfills when passed an empty array", function() {
+ return Q.any([]);
+ });
+
+ it("rejects after all promises are rejected", function() {
+ var deferreds = [Q.defer(), Q.defer()];
+ var promises = [deferreds[0].promise, deferreds[1].promise];
+
+ return testReject(promises, deferreds);
+ });
+
+ it("rejects after all promises in a sparse array are rejected", function() {
+ var deferreds = [Q.defer(), Q.defer()];
+ var promises = [];
+ promises[0] = deferreds[0].promise;
+ promises[3] = deferreds[1].promise;
+
+ return testReject(promises, deferreds);
+ });
+
+ function testReject(promises, deferreds) {
+ var promise = Q.any(promises);
+
+ for (var index = 0; index < deferreds.length; index++) {
+ var deferred = deferreds[index];
+ (function() {
+ deferred.reject(new Error('Rejected'));
+ })();
+ }
+
+ return Q.delay(250)
+ .then(function() {
+ expect(promise.isRejected()).toBe(true);
+ expect(promise.inspect().reason.message)
+ .toBe("Can't get fulfillment value from any promise, all promises were rejected.");
+ })
+ .timeout(1000);
+ }
+
+ it("fulfills with the first resolved promise", function() {
+ var deferreds = [Q.defer(), Q.defer()];
+ var promises = [deferreds[0].promise, deferreds[1].promise];
+
+ testFulfill(promises, deferreds);
+ });
+
+ it("fulfills when passed a sparse array", function() {
+ var deferreds = [Q.defer(), Q.defer()];
+ var promises = [];
+ promises[0] = deferreds[0].promise;
+ promises[2] = deferreds[1].promise;
+
+ testFulfill(promises, deferreds);
+ });
+
+ function testFulfill(promises, deferreds) {
+ var promise = Q.any(promises);
+
+ var j = 1;
+ for (var index = 0; index < deferreds.length; index++) {
+ var toResolve = deferreds[index];
+ if (!toResolve || !Q.isPromiseAlike(toResolve.promise)) {
+ continue;
+ }
+
+ (function(index, toResolve) {
+ var time = index * 50;
+ Q.delay(time).then(function() {
+ toResolve.resolve('Fulfilled' + index);
+ });
+ })(j, toResolve);
+
+ j++;
+ }
+
+ return Q.delay(400)
+ .then(function() {
+ expect(promise.isFulfilled()).toBe(true);
+ expect(promise.inspect().value).toBe('Fulfilled1');
+ })
+ .timeout(1000);
+ }
+
+ it("fulfills with the first value", function() {
+ var toResolve1 = Q.defer();
+ var toResolve2 = Q.defer();
+ var toResolve3 = Q.defer();
+ var promises = [toResolve1.promise, toResolve2.promise, 4, 5,
+ toResolve3.promise
+ ];
+
+ var promise = Q.any(promises);
+
+ Q.delay(150).then(function() {
+ toResolve1.resolve(1);
+ });
+ Q.delay(50).then(function() {
+ toResolve2.resolve(2);
+ });
+ Q.delay(100).then(function() {
+ toResolve3.resolve(3);
+ });
+
+ return Q.delay(250)
+ .then(function() {
+ expect(promise.isFulfilled()).toBe(true);
+ expect(promise.inspect().value).toBe(4);
+ })
+ .timeout(1000);
+ });
+
+ it("fulfills after rejections", function() {
+ var toReject = [Q.defer(), Q.defer()];
+ var toResolve = Q.defer();
+ var promises = [toReject[0].promise, toReject[1].promise,
+ toResolve
+ .promise
+ ];
+
+ var promise = Q.any(promises);
+
+ testFulfillAfterRejections(promises, toReject, toResolve);
+ });
+
+ it("fulfills after rejections in sparse array", function() {
+ var toReject = [Q.defer(), Q.defer()];
+ var toResolve = Q.defer();
+ var promises = [];
+ promises[2] = toReject[0].promise;
+ promises[5] = toReject[1].promise;
+ promises[9] = toResolve.promise;
+
+ testFulfillAfterRejections(promises, toReject, toResolve);
+ });
+
+ function testFulfillAfterRejections(promises, rejectDeferreds,
+ fulfillDeferred) {
+ var promise = Q.any(promises);
+
+ for (var index = 0; index < rejectDeferreds.length; index++) {
+ var toReject = rejectDeferreds[index];
+ (function(index, toReject) {
+ var time = (index + 1) * 50;
+ Q.delay(time).then(function() {
+ toReject.reject(new Error('Rejected'));
+ });
+ })(index, toReject);
+
+ index++;
+ }
+ Q.delay(index * 50).then(function() {
+ fulfillDeferred.resolve('Fulfilled');
+ });
+
+ return Q.delay(400)
+ .then(function() {
+ expect(promise.isFulfilled()).toBe(true);
+ expect(promise.inspect().value).toBe('Fulfilled');
+ })
+ .timeout(1000);
+ }
+
+ it("resolves foreign thenables", function() {
+ var normal = Q.delay(150)
+ .then(function() {})
+ .thenResolve(1);
+ var foreign = {
+ then: function(f) {
+ return f(2);
+ }
+ };
+
+ return Q.any([normal, foreign])
+ .then(function(result) {
+ expect(result).toEqual(2);
+ });
+ });
+
+ it("sends { index, value } progress updates", function() {
+ var deferred1 = Q.defer();
+ var deferred2 = Q.defer();
+
+ var progressValues = [];
+
+ Q.delay(50).then(function() {
+ deferred1.notify("a");
+ });
+ Q.delay(100).then(function() {
+ deferred2.notify("b");
+ deferred2.resolve();
+ });
+ Q.delay(150).then(function() {
+ deferred1.notify("c"); // Is lost, deferred2 already resolved.
+ deferred1.resolve();
+ });
+
+ return Q.any([deferred1.promise, deferred2.promise])
+ .delay(250)
+ .then(function() {
+ expect(progressValues).toEqual([{
+ index: 0,
+ value: "a"
+ }, {
+ index: 1,
+ value: "b"
+ }]);
+ },
+ undefined,
+ function(progressValue) {
+ progressValues.push(progressValue);
+ }
+ );
+ });
+
+});
+
describe("allSettled", function () {
it("works on an empty array", function () {
return Q.allSettled([])
@@ -2117,7 +2334,7 @@ describe("node support", function () {
});
});
-
+
describe("npost", function () {
it("fulfills with callback result", function () {
@@ -2269,7 +2486,7 @@ describe("node support", function () {
expect(ten).toBe(10);
});
});
-
+
});
});
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-q.git
More information about the Pkg-javascript-commits
mailing list