Initial commit
[yaffs-website] / node_modules / async-foreach / lib / foreach.js
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));