var loop = (function(){ return process; function isObj(v){ return v instanceof Object && typeof v === "object"; } function isIndexable(v){ return v instanceof Array || typeof v === "string" || v instanceof NodeList; } function process(v, fn){ if(isIndexable(v)) { return processArr(v, fn); } else if(isObj(v)) { return processObj(v, fn); } return false; } function processObj(o, fn){ var a = Object.keys(o), t = a.length, c = t; while(c){ var k = a[t-c--]; if(fn(k, o[k]) === true) break; } return true; } function processArr(a, fn){ var t = a.length, c = t; while(c){ var i = t-c--; if(fn(i, a[i]) === true) break; } return true; } })(); // promiseLoop: poor man's multi-promise-fulfiling loop function // o is an indexable object (array, object, string, NodeList) // cb is a function that accepts (key, value, an optional done callback), if you pass a completeFn, you must call done(); // completeFn is called when the loop is complete and all the done callbacks are called function promiseLoop(o, cb, completeFn) { // eslint-disable-line no-unused-vars 'use strict'; if(o == null) return; var errors = [], keys = Object.keys(o), doneCnt = 0, len = keys.length, broken = false, hasFn = completeFn instanceof Function, doneFn = function(k, v) { return function(err, breakNow) { if(err != null) errors.push({error: err, key: k, value: v}); if((++doneCnt === len || breakNow === true) && hasFn) { hasFn = false; // set to false in case another slower callback finishes after this. completeFn(errors.length ? errors : null, breakNow); broken = true; } } }; for(var i = 0; i < len && !broken; i++) { var k = keys[i], v = o[k]; if(cb(k, v, doneFn(k, v)) === true) return false; } return true; };