UNPKG

2.17 kBJavaScriptView Raw
1/*!
2 * Sync/Async forEach
3 * https://github.com/cowboy/javascript-sync-async-foreach
4 *
5 * Copyright (c) 2012 "Cowboy" Ben Alman
6 * Licensed under the MIT license.
7 * http://benalman.com/about/license/
8 */
9
10(function(exports) {
11
12 // Iterate synchronously or asynchronously.
13 exports.forEach = function(arr, eachFn, doneFn) {
14 var i = -1;
15 // Resolve array length to a valid (ToUint32) number.
16 var len = arr.length >>> 0;
17
18 // This IIFE is called once now, and then again, by name, for each loop
19 // iteration.
20 (function next(result) {
21 // This flag will be set to true if `this.async` is called inside the
22 // eachFn` callback.
23 var async;
24 // Was false returned from the `eachFn` callback or passed to the
25 // `this.async` done function?
26 var abort = result === false;
27
28 // Increment counter variable and skip any indices that don't exist. This
29 // allows sparse arrays to be iterated.
30 do { ++i; } while (!(i in arr) && i !== len);
31
32 // Exit if result passed to `this.async` done function or returned from
33 // the `eachFn` callback was false, or when done iterating.
34 if (abort || i === len) {
35 // If a `doneFn` callback was specified, invoke that now. Pass in a
36 // boolean value representing "not aborted" state along with the array.
37 if (doneFn) {
38 doneFn(!abort, arr);
39 }
40 return;
41 }
42
43 // Invoke the `eachFn` callback, setting `this` inside the callback to a
44 // custom object that contains one method, and passing in the array item,
45 // index, and the array.
46 result = eachFn.call({
47 // If `this.async` is called inside the `eachFn` callback, set the async
48 // flag and return a function that can be used to continue iterating.
49 async: function() {
50 async = true;
51 return next;
52 }
53 }, arr[i], i, arr);
54
55 // If the async flag wasn't set, continue by calling `next` synchronously,
56 // passing in the result of the `eachFn` callback.
57 if (!async) {
58 next(result);
59 }
60 }());
61 };
62
63}(typeof exports === "object" && exports || this));
\No newline at end of file