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 |