| /* JavaScript Sync/Async forEach - v0.1.2 - 1/10/2012 |
| * http://github.com/cowboy/javascript-sync-async-foreach |
| * Copyright (c) 2012 "Cowboy" Ben Alman; Licensed MIT */ |
| |
| (function(exports) { |
| |
| // Iterate synchronously or asynchronously. |
| exports.forEach = function(arr, eachFn, doneFn) { |
| var i = -1; |
| // Resolve array length to a valid (ToUint32) number. |
| var len = arr.length >>> 0; |
| |
| // This IIFE is called once now, and then again, by name, for each loop |
| // iteration. |
| (function next(result) { |
| // This flag will be set to true if `this.async` is called inside the |
| // eachFn` callback. |
| var async; |
| // Was false returned from the `eachFn` callback or passed to the |
| // `this.async` done function? |
| var abort = result === false; |
| |
| // Increment counter variable and skip any indices that don't exist. This |
| // allows sparse arrays to be iterated. |
| do { ++i; } while (!(i in arr) && i !== len); |
| |
| // Exit if result passed to `this.async` done function or returned from |
| // the `eachFn` callback was false, or when done iterating. |
| if (abort || i === len) { |
| // If a `doneFn` callback was specified, invoke that now. Pass in a |
| // boolean value representing "not aborted" state along with the array. |
| if (doneFn) { |
| doneFn(!abort, arr); |
| } |
| return; |
| } |
| |
| // Invoke the `eachFn` callback, setting `this` inside the callback to a |
| // custom object that contains one method, and passing in the array item, |
| // index, and the array. |
| result = eachFn.call({ |
| // If `this.async` is called inside the `eachFn` callback, set the async |
| // flag and return a function that can be used to continue iterating. |
| async: function() { |
| async = true; |
| return next; |
| } |
| }, arr[i], i, arr); |
| |
| // If the async flag wasn't set, continue by calling `next` synchronously, |
| // passing in the result of the `eachFn` callback. |
| if (!async) { |
| next(result); |
| } |
| }()); |
| }; |
| |
| }(typeof exports === "object" && exports || this)); |