1 # JavaScript Sync/Async forEach
3 An optionally-asynchronous forEach with an interesting interface.
7 This code should work just fine in Node.js:
9 First, install the module with: `npm install async-foreach`
12 var forEach = require('async-foreach').forEach;
13 forEach(["a", "b", "c"], function(item, index, arr) {
14 console.log("each", item, index, arr);
17 // each a 0 ["a", "b", "c"]
18 // each b 1 ["a", "b", "c"]
19 // each c 2 ["a", "b", "c"]
25 <script src="dist/ba-foreach.min.js"></script>
27 forEach(["a", "b", "c"], function(item, index, arr) {
28 console.log("each", item, index, arr);
31 // each a 0 ["a", "b", "c"]
32 // each b 1 ["a", "b", "c"]
33 // each c 2 ["a", "b", "c"]
37 In the browser, you can attach the forEach method to any object.
41 this.exports = Bocoup.utils;
43 <script src="dist/ba-foreach.min.js"></script>
45 Bocoup.utils.forEach(["a", "b", "c"], function(item, index, arr) {
46 console.log("each", item, index, arr);
49 // each a 0 ["a", "b", "c"]
50 // each b 1 ["a", "b", "c"]
51 // each c 2 ["a", "b", "c"]
55 ## The General Idea (Why I thought this was worth sharing)
57 The idea is to allow the callback to decide _at runtime_ whether the loop will be synchronous or asynchronous. By using `this` in a creative way (in situations where that value isn't already spoken for), an entire control API can be offered without over-complicating function signatures.
60 forEach(arr, function(item, index) {
64 forEach(arr, function(item, index) {
65 // Only when `this.async` is called does iteration becomes asynchronous. The
66 // loop won't be continued until the `done` function is executed.
67 var done = this.async();
68 // Continue in one second.
69 setTimeout(done, 1000);
72 forEach(arr, function(item, index) {
73 // Break out of synchronous iteration early by returning false.
77 forEach(arr, function(item, index) {
78 // Break out of asynchronous iteration early...
79 var done = this.async();
80 // ...by passing false to the done function.
81 setTimeout(function() {
88 See the unit tests for more examples.
91 // Generic "done" callback.
92 function allDone(notAborted, arr) {
93 console.log("done", notAborted, arr);
97 forEach(["a", "b", "c"], function(item, index, arr) {
98 console.log("each", item, index, arr);
101 // each a 0 ["a", "b", "c"]
102 // each b 1 ["a", "b", "c"]
103 // each c 2 ["a", "b", "c"]
104 // done true ["a", "b", "c"]
106 // Synchronous with early abort.
107 forEach(["a", "b", "c"], function(item, index, arr) {
108 console.log("each", item, index, arr);
109 if (item === "b") { return false; }
112 // each a 0 ["a", "b", "c"]
113 // each b 1 ["a", "b", "c"]
114 // done false ["a", "b", "c"]
117 forEach(["a", "b", "c"], function(item, index, arr) {
118 console.log("each", item, index, arr);
119 var done = this.async();
120 setTimeout(function() {
125 // each a 0 ["a", "b", "c"]
126 // each b 1 ["a", "b", "c"]
127 // each c 2 ["a", "b", "c"]
128 // done true ["a", "b", "c"]
130 // Asynchronous with early abort.
131 forEach(["a", "b", "c"], function(item, index, arr) {
132 console.log("each", item, index, arr);
133 var done = this.async();
134 setTimeout(function() {
139 // each a 0 ["a", "b", "c"]
140 // each b 1 ["a", "b", "c"]
141 // done false ["a", "b", "c"]
143 // Not actually asynchronous.
144 forEach(["a", "b", "c"], function(item, index, arr) {
145 console.log("each", item, index, arr);
146 var done = this.async()
150 // each a 0 ["a", "b", "c"]
151 // each b 1 ["a", "b", "c"]
152 // each c 2 ["a", "b", "c"]
153 // done true ["a", "b", "c"]
155 // Not actually asynchronous with early abort.
156 forEach(["a", "b", "c"], function(item, index, arr) {
157 console.log("each", item, index, arr);
158 var done = this.async();
162 // each a 0 ["a", "b", "c"]
163 // each b 1 ["a", "b", "c"]
164 // done false ["a", "b", "c"]
168 In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [grunt](https://github.com/cowboy/grunt).
170 _Also, please don't edit files in the "dist" subdirectory as they are generated via grunt. You'll find source code in the "lib" subdirectory!_
176 Removed hard Node.js version dependency.
180 Adding sparse array support.
181 Invalid length properties are now sanitized.
182 This closes issue #1 (like a boss).
186 Refactored code to be much simpler. Yay for unit tests!
193 Copyright (c) 2012 "Cowboy" Ben Alman
194 Licensed under the MIT license.
195 <http://benalman.com/about/license/>