UNPKG

4.98 kBMarkdownView Raw
1# JavaScript Sync/Async forEach
2
3An optionally-asynchronous forEach with an interesting interface.
4
5## Getting Started
6
7This code should work just fine in Node.js:
8
9First, install the module with: `npm install async-foreach`
10
11```javascript
12var forEach = require('async-foreach').forEach;
13forEach(["a", "b", "c"], function(item, index, arr) {
14 console.log("each", item, index, arr);
15});
16// logs:
17// each a 0 ["a", "b", "c"]
18// each b 1 ["a", "b", "c"]
19// each c 2 ["a", "b", "c"]
20```
21
22Or in the browser:
23
24```html
25<script src="dist/ba-foreach.min.js"></script>
26<script>
27forEach(["a", "b", "c"], function(item, index, arr) {
28 console.log("each", item, index, arr);
29});
30// logs:
31// each a 0 ["a", "b", "c"]
32// each b 1 ["a", "b", "c"]
33// each c 2 ["a", "b", "c"]
34</script>
35```
36
37In the browser, you can attach the forEach method to any object.
38
39```html
40<script>
41this.exports = Bocoup.utils;
42</script>
43<script src="dist/ba-foreach.min.js"></script>
44<script>
45Bocoup.utils.forEach(["a", "b", "c"], function(item, index, arr) {
46 console.log("each", item, index, arr);
47});
48// logs:
49// each a 0 ["a", "b", "c"]
50// each b 1 ["a", "b", "c"]
51// each c 2 ["a", "b", "c"]
52</script>
53```
54
55## The General Idea (Why I thought this was worth sharing)
56
57The 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.
58
59```javascript
60forEach(arr, function(item, index) {
61 // Synchronous.
62});
63
64forEach(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);
70});
71
72forEach(arr, function(item, index) {
73 // Break out of synchronous iteration early by returning false.
74 return index !== 1;
75});
76
77forEach(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() {
82 done(index !== 1);
83 });
84});
85```
86
87## Examples
88See the unit tests for more examples.
89
90```javascript
91// Generic "done" callback.
92function allDone(notAborted, arr) {
93 console.log("done", notAborted, arr);
94}
95
96// Synchronous.
97forEach(["a", "b", "c"], function(item, index, arr) {
98 console.log("each", item, index, arr);
99}, allDone);
100// logs:
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"]
105
106// Synchronous with early abort.
107forEach(["a", "b", "c"], function(item, index, arr) {
108 console.log("each", item, index, arr);
109 if (item === "b") { return false; }
110}, allDone);
111// logs:
112// each a 0 ["a", "b", "c"]
113// each b 1 ["a", "b", "c"]
114// done false ["a", "b", "c"]
115
116// Asynchronous.
117forEach(["a", "b", "c"], function(item, index, arr) {
118 console.log("each", item, index, arr);
119 var done = this.async();
120 setTimeout(function() {
121 done();
122 }, 500);
123}, allDone);
124// logs:
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"]
129
130// Asynchronous with early abort.
131forEach(["a", "b", "c"], function(item, index, arr) {
132 console.log("each", item, index, arr);
133 var done = this.async();
134 setTimeout(function() {
135 done(item !== "b");
136 }, 500);
137}, allDone);
138// logs:
139// each a 0 ["a", "b", "c"]
140// each b 1 ["a", "b", "c"]
141// done false ["a", "b", "c"]
142
143// Not actually asynchronous.
144forEach(["a", "b", "c"], function(item, index, arr) {
145 console.log("each", item, index, arr);
146 var done = this.async()
147 done();
148}, allDone);
149// logs:
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"]
154
155// Not actually asynchronous with early abort.
156forEach(["a", "b", "c"], function(item, index, arr) {
157 console.log("each", item, index, arr);
158 var done = this.async();
159 done(item !== "b");
160}, allDone);
161// logs:
162// each a 0 ["a", "b", "c"]
163// each b 1 ["a", "b", "c"]
164// done false ["a", "b", "c"]
165```
166
167## Contributing
168In 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).
169
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!_
171
172## Release History
173
17404/29/2013
175v0.1.3
176Removed hard Node.js version dependency.
177
17811/17/2011
179v0.1.2
180Adding sparse array support.
181Invalid length properties are now sanitized.
182This closes issue #1 (like a boss).
183
18411/11/2011
185v0.1.1
186Refactored code to be much simpler. Yay for unit tests!
187
18811/11/2011
189v0.1.0
190Initial Release.
191
192## License
193Copyright (c) 2012 "Cowboy" Ben Alman
194Licensed under the MIT license.
195<http://benalman.com/about/license/>