Repository: caolan/async
Pull request #1558 (2018-07-09 16:22:45)

Add limit value to `mapLimit` example


Patch:
diff --git a/intro.md b/intro.md
index dc4b29c..1bc29e3 100644
--- a/intro.md
+++ b/intro.md
@@ -124,7 +124,7 @@ It is always good practice to `return callback(err, result)`  whenever a callbac
 Async accepts `async` functions wherever we accept a Node-style callback function.  However, we do not pass them a callback, and instead use the return value and handle any promise rejections or errors thrown.
 
 ```js
-async.mapLimit(files, async file => { // <- no callback!
+async.mapLimit(files, 10, async file => { // <- no callback!
     const text = await util.promisify(fs.readFile)(dir + file, 'utf8')
     const body = JSON.parse(text) // <- a parse error herre will be caught automatically
     if (!(await checkValidity(body))) {
diff --git a/lib/internal/DoublyLinkedList.js b/lib/internal/DoublyLinkedList.js
index 4444bcb..39f88ac 100644
--- a/lib/internal/DoublyLinkedList.js
+++ b/lib/internal/DoublyLinkedList.js
@@ -60,14 +60,16 @@ export default class DLL {
         return this.tail && this.removeLink(this.tail);
     }
 
-    toArray () {
-        var arr = Array(this.length);
-        var curr = this.head;
-        for(var idx = 0; idx < this.length; idx++) {
-            arr[idx] = curr.data;
-            curr = curr.next;
+    toArray() {
+        return [...this]
+    }
+
+    *[Symbol.iterator] () {
+        var cur = this.head
+        while (cur) {
+            yield cur.data
+            cur = cur.next
         }
-        return arr;
     }
 
     remove (testFn) {
diff --git a/lib/internal/queue.js b/lib/internal/queue.js
index a811080..4c1f5cc 100644
--- a/lib/internal/queue.js
+++ b/lib/internal/queue.js
@@ -87,6 +87,9 @@ export default function queue(worker, concurrency, payload) {
     var isProcessing = false;
     var q = {
         _tasks: new DLL(),
+        *[Symbol.iterator] () {
+            yield* q._tasks[Symbol.iterator]()
+        },
         concurrency,
         payload,
         saturated: noop,
diff --git a/lib/queue.js b/lib/queue.js
index 00b90ce..0fa7b96 100644
--- a/lib/queue.js
+++ b/lib/queue.js
@@ -3,7 +3,7 @@ import wrapAsync from './internal/wrapAsync';
 
 /**
  * A queue of tasks for the worker function to complete.
- * @typedef {Object} QueueObject
+ * @typedef {Iterable} QueueObject
  * @memberOf module:ControlFlow
  * @property {Function} length - a function returning the number of items
  * waiting to be processed. Invoke with `queue.length()`.
@@ -53,6 +53,18 @@ import wrapAsync from './internal/wrapAsync';
  * @property {Function} kill - a function that removes the `drain` callback and
  * empties remaining tasks from the queue forcing it to go idle. No more tasks
  * should be pushed to the queue after calling this function. Invoke with `queue.kill()`.
+ *
+ * @example
+ * const q = aync.queue(worker, 2)
+ * q.push(item1)
+ * q.push(item2)
+ * q.push(item3)
+ * // queues are iterable, spread into an array to inspect
+ * const items = [...q] // [item1, item2, item3]
+ * // or use for of
+ * for (let item of q) {
+ *     console.log(item)
+ * }
  */
 
 /**


Test patch:
diff --git a/test/queue.js b/test/queue.js
index 3eeeac8..2ac5077 100644
--- a/test/queue.js
+++ b/test/queue.js
@@ -799,4 +799,23 @@ describe('queue', function(){
             done();
         }
     });
+
+    it('should be iterable', (done) => {
+        var q = async.queue((data, cb) => {
+            if (data === 3) {
+                q.push(6)
+                expect([...q]).to.eql([4, 5, 6]);
+            }
+            async.setImmediate(cb);
+        });
+
+        q.push([1, 2, 3, 4, 5]);
+
+        expect([...q]).to.eql([1, 2, 3, 4, 5]);
+
+        q.drain = function () {
+            expect([...q]).to.eql([]);
+            done();
+        }
+    })
 });