[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