[Pkg-javascript-commits] [node-async] 119/480: Imported Upstream version 0.1.15~20111104

Jonas Smedegaard js at moszumanska.debian.org
Fri May 2 08:58:18 UTC 2014


This is an automated email from the git hooks/post-receive script.

js pushed a commit to branch master
in repository node-async.

commit fedf85654fd96077aed472399aec4865373bb3c1
Author: Jonas Smedegaard <dr at jones.dk>
Date:   Sun Dec 4 19:08:05 2011 +0700

    Imported Upstream version 0.1.15~20111104
---
 README.md          |  49 +++++++++++++--
 dist/async.min.js  |   2 +-
 lib/async.js       |  91 +++++++++++++++++++++------
 package.json       |   4 +-
 test/test-async.js | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 297 insertions(+), 25 deletions(-)

diff --git a/README.md b/README.md
index 31f5a42..94ee562 100644
--- a/README.md
+++ b/README.md
@@ -96,6 +96,7 @@ So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:
 ### Utils
 
 * [memoize](#memoize)
+* [unmemoize](#unmemoize)
 * [log](#log)
 * [dir](#dir)
 * [noConflict](#noConflict)
@@ -143,6 +144,32 @@ processing. This means the iterator functions will complete in order.
 
 ---------------------------------------
 
+<a name="forEachLimit" />
+### forEachLimit(arr, limit, iterator, callback)
+
+The same as forEach only the iterator is applied to batches of items in the
+array, in series. The next batch of iterators is only called once the current
+one has completed processing.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* limit - How many items should be in each batch.
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback which must be called once it has completed.
+* callback(err) - A callback which is called after all the iterator functions
+  have finished, or an error has occurred.
+
+__Example__
+
+    // Assume documents is an array of JSON objects and requestApi is a
+    // function that interacts with a rate-limited REST api.
+
+    async.forEachLimit(documents, 20, requestApi, function(err){
+        // if any of the saves produced an error, err would equal that error
+    });
+---------------------------------------
+
 <a name="map" />
 ### map(arr, iterator, callback)
 
@@ -599,7 +626,7 @@ __Example__
         function (err) {
             // 5 seconds have passed
         }
-    });
+    );
 
 
 ---------------------------------------
@@ -683,7 +710,7 @@ __Example__
     // create a queue object with concurrency 2
 
     var q = async.queue(function (task, callback) {
-        console.log('hello ' + task.name).
+        console.log('hello ' + task.name);
         callback();
     }, 2);
 
@@ -711,9 +738,10 @@ __Example__
 Determines the best order for running functions based on their requirements.
 Each function can optionally depend on other functions being completed first,
 and each function is run as soon as its requirements are satisfied. If any of
-the functions pass and error to their callback, that function will not complete
+the functions pass an error to their callback, that function will not complete
 (so any other functions depending on it will not run) and the main callback
-will be called immediately with the error.
+will be called immediately with the error. Functions also receive an object
+containing the results of functions on which they depend.
 
 __Arguments__
 
@@ -737,9 +765,11 @@ __Example__
         write_file: ['get_data', 'make_folder', function(callback){
             // once there is some data and the directory exists,
             // write the data to a file in the directory
+            callback(null, filename);
         }],
-        email_link: ['write_file', function(callback){
+        email_link: ['write_file', function(callback, results){
             // once the file is written let's email a link to it...
+            // results.write_file contains the filename returned by write_file.
         }]
     });
 
@@ -907,6 +937,15 @@ __Example__
         // callback
     });
 
+<a name="unmemoize" />
+### unmemoize(fn)
+
+Undoes a memoized function, reverting it to the original, unmemoized
+form. Comes handy in tests.
+
+__Arguments__
+
+* fn - the memoized function
 
 <a name="log" />
 ### log(function, arguments)
diff --git a/dist/async.min.js b/dist/async.min.js
index bf3c3aa..e4c898b 100644
--- a/dist/async.min.js
+++ b/dist/async.min.js
@@ -1 +1 @@
-/*global setTimeout: false, console: false */(function(){var a={},b=this,c=b.async;typeof module!="undefined"&&module.exports?module.exports=a:b.async=a,a.noConflict=function(){b.async=c;return a};var d=function(a,b){if(a.forEach)return a.forEach(b);for(var c=0;c<a.length;c+=1)b(a[c],c,a)},e=function(a,b){if(a.map)return a.map(b);var c=[];d(a,function(a,d,e){c.push(b(a,d,e))});return c},f=function(a,b,c){if(a.reduce)return a.reduce(b,c);d(a,function(a,d,e){c=b(c,a,d,e)});return c},g=func [...]
\ No newline at end of file
+/*global setTimeout: false, console: false */(function(){var a={},b=this,c=b.async;typeof module!="undefined"&&module.exports?module.exports=a:b.async=a,a.noConflict=function(){return b.async=c,a};var d=function(a,b){if(a.forEach)return a.forEach(b);for(var c=0;c<a.length;c+=1)b(a[c],c,a)},e=function(a,b){if(a.map)return a.map(b);var c=[];return d(a,function(a,d,e){c.push(b(a,d,e))}),c},f=function(a,b,c){return a.reduce?a.reduce(b,c):(d(a,function(a,d,e){c=b(c,a,d,e)}),c)},g=function(a){ [...]
\ No newline at end of file
diff --git a/lib/async.js b/lib/async.js
index 73eddc8..c862008 100644
--- a/lib/async.js
+++ b/lib/async.js
@@ -133,6 +133,42 @@
         };
         iterate();
     };
+    
+    async.forEachLimit = function (arr, limit, iterator, callback) {
+        if (!arr.length || limit <= 0) {
+            return callback(); 
+        }
+        var completed = 0;
+        var started = 0;
+        var running = 0;
+        
+        (function replenish () {
+          if (completed === arr.length) {
+              return callback();
+          }
+          
+          while (running < limit && started < arr.length) {
+            iterator(arr[started], function (err) {
+              if (err) {
+                  callback(err);
+                  callback = function () {};
+              }
+              else {
+                  completed += 1;
+                  running -= 1;
+                  if (completed === arr.length) {
+                      callback();
+                  }
+                  else {
+                      replenish();
+                  }
+              }
+            });
+            started += 1;
+            running += 1;
+          }
+        })();
+    };
 
 
     var doParallel = function (fn) {
@@ -325,7 +361,7 @@
             return callback(null);
         }
 
-        var completed = [];
+        var results = {};
 
         var listeners = [];
         var addListener = function (fn) {
@@ -346,8 +382,8 @@
         };
 
         addListener(function () {
-            if (completed.length === keys.length) {
-                callback(null);
+            if (_keys(results).length === keys.length) {
+                callback(null, results);
             }
         });
 
@@ -360,24 +396,28 @@
                     callback = function () {};
                 }
                 else {
-                    completed.push(k);
+                    var args = Array.prototype.slice.call(arguments, 1);
+                    if (args.length <= 1) {
+                        args = args[0];
+                    }
+                    results[k] = args;
                     taskComplete();
                 }
             };
             var requires = task.slice(0, Math.abs(task.length - 1)) || [];
             var ready = function () {
                 return _reduce(requires, function (a, x) {
-                    return (a && _indexOf(completed, x) !== -1);
+                    return (a && results.hasOwnProperty(x));
                 }, true);
             };
             if (ready()) {
-                task[task.length - 1](taskCallback);
+                task[task.length - 1](taskCallback, results);
             }
             else {
                 var listener = function () {
                     if (ready()) {
                         removeListener(listener);
-                        task[task.length - 1](taskCallback);
+                        task[task.length - 1](taskCallback, results);
                     }
                 };
                 addListener(listener);
@@ -547,34 +587,34 @@
 
     async.queue = function (worker, concurrency) {
         var workers = 0;
-        var tasks = [];
         var q = {
+            tasks: [],
             concurrency: concurrency,
             saturated: null,
             empty: null,
             drain: null,
             push: function (data, callback) {
-                tasks.push({data: data, callback: callback});
-                if(q.saturated && tasks.length == concurrency) q.saturated();
+                q.tasks.push({data: data, callback: callback});
+                if(q.saturated && q.tasks.length == concurrency) q.saturated();
                 async.nextTick(q.process);
             },
             process: function () {
-                if (workers < q.concurrency && tasks.length) {
-                    var task = tasks.shift();
-                    if(q.empty && tasks.length == 0) q.empty();
+                if (workers < q.concurrency && q.tasks.length) {
+                    var task = q.tasks.shift();
+                    if(q.empty && q.tasks.length == 0) q.empty();
                     workers += 1;
                     worker(task.data, function () {
                         workers -= 1;
                         if (task.callback) {
                             task.callback.apply(task, arguments);
                         }
-                        if(q.drain && tasks.length + workers == 0) q.drain();
+                        if(q.drain && q.tasks.length + workers == 0) q.drain();
                         q.process();
                     });
                 }
             },
             length: function () {
-                return tasks.length;
+                return q.tasks.length;
             },
             running: function () {
                 return workers;
@@ -611,23 +651,40 @@
 
     async.memoize = function (fn, hasher) {
         var memo = {};
+        var queues = {};
         hasher = hasher || function (x) {
             return x;
         };
-        return function () {
+        var memoized = function () {
             var args = Array.prototype.slice.call(arguments);
             var callback = args.pop();
             var key = hasher.apply(null, args);
             if (key in memo) {
                 callback.apply(null, memo[key]);
             }
+            else if (key in queues) {
+                queues[key].push(callback);
+            }
             else {
+                queues[key] = [callback];
                 fn.apply(null, args.concat([function () {
                     memo[key] = arguments;
-                    callback.apply(null, arguments);
+                    var q = queues[key];
+                    delete queues[key];
+                    for (var i = 0, l = q.length; i < l; i++) {
+                      q[i].apply(null, arguments);
+                    }
                 }]));
             }
         };
+        memoized.unmemoized = fn;
+        return memoized;
+    };
+
+    async.unmemoize = function (fn) {
+      return function () {
+        return (fn.unmemoized || fn).apply(null, arguments);
+      }
     };
 
 }());
diff --git a/package.json b/package.json
index f995464..6198943 100644
--- a/package.json
+++ b/package.json
@@ -2,12 +2,12 @@
 , "description": "Higher-order functions and common patterns for asynchronous code"
 , "main": "./index"
 , "author": "Caolan McMahon"
-, "version": "0.1.9"
+, "version": "0.1.15"
 , "repository" :
   { "type" : "git"
   , "url" : "http://github.com/caolan/async.git"
   }
-, "bugs" : { "web" : "http://github.com/caolan/async/issues" }
+, "bugs" : { "url" : "http://github.com/caolan/async/issues" }
 , "licenses" :
   [ { "type" : "MIT"
     , "url" : "http://github.com/caolan/async/raw/master/LICENSE"
diff --git a/test/test-async.js b/test/test-async.js
index 4a7f986..d3eeddc 100644
--- a/test/test-async.js
+++ b/test/test-async.js
@@ -32,6 +32,42 @@ exports['auto'] = function(test){
     });
 };
 
+exports['auto results'] = function(test){
+    var callOrder = [];
+    async.auto({
+      task1: ['task2', function(callback, results){
+          test.same(results.task2, 'task2');
+          setTimeout(function(){
+              callOrder.push('task1');
+              callback(null, 'task1a', 'task1b');
+          }, 25);
+      }],
+      task2: function(callback){
+          setTimeout(function(){
+              callOrder.push('task2');
+              callback(null, 'task2');
+          }, 50);
+      },
+      task3: ['task2', function(callback, results){
+          test.same(results.task2, 'task2');
+          callOrder.push('task3');
+          callback(null);
+      }],
+      task4: ['task1', 'task2', function(callback, results){
+          test.same(results.task1, ['task1a','task1b']);
+          test.same(results.task2, 'task2');
+          callOrder.push('task4');
+          callback(null, 'task4');
+      }]
+    },
+    function(err, results){
+        test.same(callOrder, ['task2','task3','task1','task4']);
+        test.same(results, {task1: ['task1a','task1b'], task2: 'task2', task3: undefined, task4: 'task4'});
+        test.done();
+    });
+};
+
+
 exports['auto empty object'] = function(test){
     async.auto({}, function(err){
         test.done();
@@ -491,6 +527,87 @@ exports['forEachSeries error'] = function(test){
     setTimeout(test.done, 50);
 };
 
+exports['forEachLimit'] = function(test){
+    var args = [];
+    var arr = [0,1,2,3,4,5,6,7,8,9];
+    async.forEachLimit(arr, 2, function(x,callback){
+        setTimeout(function(){
+            args.push(x);
+            callback();
+        }, x*5);
+    }, function(err){
+        test.same(args, arr);
+        test.done();
+    });
+};
+
+exports['forEachLimit empty array'] = function(test){
+    test.expect(1);
+    async.forEachLimit([], 2, function(x, callback){
+        test.ok(false, 'iterator should not be called');
+        callback();
+    }, function(err){
+        test.ok(true, 'should call callback');
+    });
+    setTimeout(test.done, 25);
+};
+
+exports['forEachLimit limit exceeds size'] = function(test){
+    var args = [];
+    var arr = [0,1,2,3,4,5,6,7,8,9];
+    async.forEachLimit(arr, 20, function(x,callback){
+        setTimeout(function(){
+            args.push(x);
+            callback();
+        }, x*5);
+    }, function(err){
+        test.same(args, arr);
+        test.done();
+    });
+};
+
+exports['forEachLimit limit equal size'] = function(test){
+    var args = [];
+    var arr = [0,1,2,3,4,5,6,7,8,9];
+    async.forEachLimit(arr, 10, function(x,callback){
+        setTimeout(function(){
+            args.push(x);
+            callback();
+        }, x*5);
+    }, function(err){
+        test.same(args, arr);
+        test.done();
+    });
+};
+
+exports['forEachLimit zero limit'] = function(test){
+    test.expect(1);
+    async.forEachLimit([0,1,2,3,4,5], 0, function(x, callback){
+        test.ok(false, 'iterator should not be called');
+        callback();
+    }, function(err){
+        test.ok(true, 'should call callback');
+    });
+    setTimeout(test.done, 25);
+};
+
+exports['forEachLimit error'] = function(test){
+    test.expect(2);
+    var arr = [0,1,2,3,4,5,6,7,8,9];
+    var call_order = [];
+    
+    async.forEachLimit(arr, 3, function(x, callback){
+        call_order.push(x);
+        if (x === 2) {
+            callback('error');
+        }
+    }, function(err){
+        test.same(call_order, [0,1,2]);
+        test.equals(err, 'error');
+    });
+    setTimeout(test.done, 25);
+};
+
 exports['map'] = function(test){
     var call_order = [];
     async.map([1,3,2], function(x, callback){
@@ -1253,6 +1370,47 @@ exports['memoize'] = function (test) {
     test.done();
 };
 
+exports['unmemoize'] = function(test) {
+    test.expect(4);
+    var call_order = [];
+
+    var fn = function (arg1, arg2, callback) {
+        call_order.push(['fn', arg1, arg2]);
+        callback(null, arg1 + arg2);
+    };
+
+    var fn2 = async.memoize(fn);
+    var fn3 = async.unmemoize(fn2);
+    fn3(1, 2, function (err, result) {
+        test.equal(result, 3);
+    });
+    fn3(1, 2, function (err, result) {
+        test.equal(result, 3);
+    });
+    fn3(2, 2, function (err, result) {
+        test.equal(result, 4);
+    });
+
+    test.same(call_order, [['fn',1,2], ['fn',1,2], ['fn',2,2]]);
+
+    test.done();
+}
+
+exports['unmemoize a not memoized function'] = function(test) {
+    test.expect(1);
+
+    var fn = function (arg1, arg2, callback) {
+        callback(null, arg1 + arg2);
+    };
+
+    var fn2 = async.unmemoize(fn);
+    fn2(1, 2, function(err, result) {
+        test.equal(result, 3);
+    });
+
+    test.done();
+}
+
 exports['memoize error'] = function (test) {
     test.expect(1);
     var testerr = new Error('test');
@@ -1265,6 +1423,24 @@ exports['memoize error'] = function (test) {
     test.done();
 };
 
+exports['memoize multiple calls'] = function (test) {
+    test.expect(3);
+    var fn = function (arg1, arg2, callback) {
+        test.ok(true);
+        setTimeout(function(){
+            callback(null, arg1, arg2);
+        }, 10);
+    };
+    var fn2 = async.memoize(fn);
+    fn2(1, 2, function(err, result) {
+        test.equal(result, 1, 2);
+    });
+    fn2(1, 2, function(err, result) {
+        test.equal(result, 1, 2);
+        test.done();
+    });
+};
+
 exports['memoize custom hash function'] = function (test) {
     test.expect(2);
     var testerr = new Error('test');

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-async.git



More information about the Pkg-javascript-commits mailing list