1// MIT license (by Elan Shanker). 2(function(globals) { 3 'use strict'; 4 5 var executeSync = function(){ 6 var args = Array.prototype.slice.call(arguments); 7 if (typeof args[0] === 'function'){ 8 args[0].apply(null, args.splice(1)); 9 } 10 }; 11 12 var executeAsync = function(fn){ 13 if (typeof setImmediate === 'function') { 14 setImmediate(fn); 15 } else if (typeof process !== 'undefined' && process.nextTick) { 16 process.nextTick(fn); 17 } else { 18 setTimeout(fn, 0); 19 } 20 }; 21 22 var makeIterator = function (tasks) { 23 var makeCallback = function (index) { 24 var fn = function () { 25 if (tasks.length) { 26 tasks[index].apply(null, arguments); 27 } 28 return fn.next(); 29 }; 30 fn.next = function () { 31 return (index < tasks.length - 1) ? makeCallback(index + 1): null; 32 }; 33 return fn; 34 }; 35 return makeCallback(0); 36 }; 37 38 var _isArray = Array.isArray || function(maybeArray){ 39 return Object.prototype.toString.call(maybeArray) === '[object Array]'; 40 }; 41 42 var waterfall = function (tasks, callback, forceAsync) { 43 var nextTick = forceAsync ? executeAsync : executeSync; 44 callback = callback || function () {}; 45 if (!_isArray(tasks)) { 46 var err = new Error('First argument to waterfall must be an array of functions'); 47 return callback(err); 48 } 49 if (!tasks.length) { 50 return callback(); 51 } 52 var wrapIterator = function (iterator) { 53 return function (err) { 54 if (err) { 55 callback.apply(null, arguments); 56 callback = function () {}; 57 } else { 58 var args = Array.prototype.slice.call(arguments, 1); 59 var next = iterator.next(); 60 if (next) { 61 args.push(wrapIterator(next)); 62 } else { 63 args.push(callback); 64 } 65 nextTick(function () { 66 iterator.apply(null, args); 67 }); 68 } 69 }; 70 }; 71 wrapIterator(makeIterator(tasks))(); 72 }; 73 74 if (typeof define !== 'undefined' && define.amd) { 75 define([], function () { 76 return waterfall; 77 }); // RequireJS 78 } else if (typeof module !== 'undefined' && module.exports) { 79 module.exports = waterfall; // CommonJS 80 } else { 81 globals.waterfall = waterfall; // <script> 82 } 83})(this); 84