You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
63 lines
2.1 KiB
63 lines
2.1 KiB
/*! |
|
* Sync/Async forEach |
|
* https://github.com/cowboy/javascript-sync-async-foreach |
|
* |
|
* Copyright (c) 2012 "Cowboy" Ben Alman |
|
* Licensed under the MIT license. |
|
* http://benalman.com/about/license/ |
|
*/ |
|
|
|
(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)); |