Compare commits
	
		
			No commits in common. "178672ad0d974e1fc1ee384e491fde529a58cbbd" and "038b6cac33806d6b4ad8ddc9de2a79759728ecf8" have entirely different histories.
		
	
	
		
			178672ad0d
			...
			038b6cac33
		
	
		
							
								
								
									
										127
									
								
								batchasync.js
									
									
									
									
									
								
							
							
						
						
									
										127
									
								
								batchasync.js
									
									
									
									
									
								
							| @ -1,70 +1,71 @@ | |||||||
| (function(exports) { | (function (exports) { | ||||||
|     "use strict"; | 'use strict'; | ||||||
| 
 | 
 | ||||||
|     exports.batchAsync = function(limit, arr, doStuff) { | exports.batchAsync = function (limit, arr, doStuff) { | ||||||
|         arr = arr.slice(0); | 	arr = arr.slice(0); | ||||||
|         return new Promise(function(resolve, reject) { | 	return new Promise(function(resolve, reject) { | ||||||
|             var total = arr.length; | 		var total = arr.length; | ||||||
|             var active = 0; | 		var active = 0; | ||||||
|             var results = []; | 		var results = []; | ||||||
|             var error; | 		var error; | ||||||
| 
 | 
 | ||||||
|             function doMoreStuff() { | 		function doMoreStuff() { | ||||||
|                 // Don't take on any more tasks if we've errored,
 | 			// Don't take on any more tasks if we've errored,
 | ||||||
|                 // or if too many are already in progress
 | 			// or if too many are already in progress
 | ||||||
|                 if (error || active > limit) { | 			if (error || active > limit) { | ||||||
|                     return; | 				return; | ||||||
|                 } | 			} | ||||||
| 
 | 
 | ||||||
|                 // If there are no more tasks to start, return
 | 			// If there are no more tasks to start, return
 | ||||||
|                 if (!arr.length) { | 			if (!arr.length) { | ||||||
|                     // If everything is also *finished*, resolve
 | 				// If everything is also *finished*, resolve
 | ||||||
|                     if (active < 1) { | 				if (active < 1) { | ||||||
|                         resolve(results); | 					resolve(results); | ||||||
|                     } | 				} | ||||||
|                     return; | 				return; | ||||||
|                 } | 			} | ||||||
| 
 | 
 | ||||||
|                 // We need to dequeue the task here so the index is correct
 | 			// We need to dequeue the task here so the index is correct
 | ||||||
|                 // (keep in mind we want to support sync and async)
 | 			// (keep in mind we want to support sync and async)
 | ||||||
|                 var index = total - arr.length; | 			var index = total - arr.length; | ||||||
|                 var task = arr.shift(); | 			var task = arr.shift(); | ||||||
|                 active += 1; | 			active += 1; | ||||||
| 
 | 
 | ||||||
|                 // Spawn another task immediately,
 | 			// Spawn another task immediately,
 | ||||||
|                 // which will be stopped if we're at the limit
 | 			// which will be stopped if we're at the limit
 | ||||||
|                 doMoreStuff(); | 			doMoreStuff(); | ||||||
| 
 | 
 | ||||||
|                 var p; | 			var p; | ||||||
|                 try { | 			try { | ||||||
|                     p = doStuff(task, index, arr); | 				p = doStuff(task); | ||||||
|                 } catch (e) { | 			} catch (e) { | ||||||
|                     // we need to handle, and bubble, synchronous errors
 | 				// we need to handle, and bubble, synchronous errors
 | ||||||
|                     error = e; | 				error = e; | ||||||
|                     reject(e); | 				reject(e); | ||||||
|                     throw e; | 				throw e; | ||||||
|                 } | 			} | ||||||
|                 // Do stuff and then decrease the active counter when done
 | 			// Do stuff and then decrease the active counter when done
 | ||||||
|                 // add support for sync by rapping in a promise
 | 			// add support for sync by rapping in a promise
 | ||||||
|                 Promise.resolve(p) | 			Promise.resolve(p) | ||||||
|                     .then(function(result) { | 				.then(function(result) { | ||||||
|                         if ("undefined" === typeof result) { | 					if ('undefined' === typeof result) { | ||||||
|                             throw new Error( | 						throw new Error( | ||||||
|                                 "result was 'undefined'. Please return 'null' to signal that you didn't just forget to return another promise." | 							"result was 'undefined'. Please return 'null' to signal that you didn't just forget to return another promise." | ||||||
|                             ); | 						); | ||||||
|                         } | 					} | ||||||
|                         active -= 1; | 					active -= 1; | ||||||
|                         results[index] = result; | 					results[index] = result; | ||||||
|                     }) | 				}) | ||||||
|                     .then(doMoreStuff) | 				.then(doMoreStuff) | ||||||
|                     .catch(function(e) { | 				.catch(function(e) { | ||||||
|                         // handle async errors
 | 					// handle async errors
 | ||||||
|                         error = e; | 					error = e; | ||||||
|                         reject(e); | 					reject(e); | ||||||
|                     }); | 				}); | ||||||
|             } | 		} | ||||||
| 
 | 
 | ||||||
|             doMoreStuff(); | 		doMoreStuff(); | ||||||
|         }); | 	}); | ||||||
|     }; | }; | ||||||
| })("undefined" !== typeof window ? window : module.exports); | 
 | ||||||
|  | }('undefined' !== typeof window ? window : module.exports)); | ||||||
|  | |||||||
							
								
								
									
										5
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1,5 +0,0 @@ | |||||||
| { |  | ||||||
|   "name": "batchasync", |  | ||||||
|   "version": "1.0.3", |  | ||||||
|   "lockfileVersion": 1 |  | ||||||
| } |  | ||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "batchasync", |   "name": "batchasync", | ||||||
|   "version": "1.0.3", |   "version": "1.0.2", | ||||||
|   "description": "Like forEachAsync, or Promise.all(), but handling a bounded number of items at any given time.", |   "description": "Like forEachAsync, or Promise.all(), but handling a bounded number of items at any given time.", | ||||||
|   "main": "batchasync.js", |   "main": "batchasync.js", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|  | |||||||
							
								
								
									
										211
									
								
								test.js
									
									
									
									
									
								
							
							
						
						
									
										211
									
								
								test.js
									
									
									
									
									
								
							| @ -1,111 +1,110 @@ | |||||||
| (function(exports) { | (function (exports) { | ||||||
|     "use strict"; | 'use strict'; | ||||||
| 
 | 
 | ||||||
|     var batchAsync = | var batchAsync = exports.batchAsync || require('./batchasync.js').batchAsync; | ||||||
|         exports.batchAsync || require("./batchasync.js").batchAsync; |  | ||||||
| 
 | 
 | ||||||
|     function testBatch() { | function testBatch() { | ||||||
|         var timeouts = [100, 80, 20, 500, 50, 30, 200, 300]; | 	var timeouts = [100, 80, 20, 500, 50, 30, 200, 300]; | ||||||
|         console.info(timeouts); | 	var tasks = timeouts.map(function(timeout, i) { | ||||||
|         var tasks = timeouts.map(function(timeout, i) { | 		return function() { | ||||||
|             return function() { | 			return promiseTimeout(timeout).then(function() { | ||||||
|                 return promiseTimeout(timeout).then(function() { | 				console.log('task:', i, timeouts[i]); | ||||||
|                     //console.log("task:", i, timeouts[i]);
 | 				return i; | ||||||
|                     return i + ":" + timeouts[i]; | 			}); | ||||||
|                 }); | 		}; | ||||||
|             }; | 	}); | ||||||
|         }); | 	var len = tasks.length; | ||||||
|         var len = tasks.length; |  | ||||||
| 
 | 
 | ||||||
|         return batchAsync(4, tasks, function(task) { | 	return batchAsync(4, tasks, function(task) { | ||||||
|             return task(); | 		return task(); | ||||||
|         }) | 	}) | ||||||
|             .then(function(results) { | 		.then(function(results) { | ||||||
|                 console.info("results:", results); | 			console.info('results:', results); | ||||||
|                 if (len !== results.length) { | 			if (len !== results.length) { | ||||||
|                     throw new Error("result set too small"); | 				throw new Error('result set too small'); | ||||||
|                 } | 			} | ||||||
|                 if (results.join(" ") !== results.sort().join(" ")) { | 			if (results.join(' ') !== results.sort().join(' ')) { | ||||||
|                     throw new Error("result set out-of-order"); | 				throw new Error('result set out-of-order'); | ||||||
|                 } | 			} | ||||||
|             }) | 		}) | ||||||
|             .then(function() { | 		.then(function() { | ||||||
|                 return batchAsync(4, [], "not a function").then(function() { | 			return batchAsync(4, [], 'not a function').then(function() { | ||||||
|                     console.info("Handled ZERO tasks correctly."); | 				console.info('Handled ZERO tasks correctly.'); | ||||||
|                 }); | 			}); | ||||||
|             }) | 		}) | ||||||
|             .then(function() { | 		.then(function() { | ||||||
|                 return batchAsync(4, timeouts, function(x) { | 			return batchAsync(4, timeouts, function(x) { | ||||||
|                     return x; | 				return x; | ||||||
|                 }).then(function(results) { | 			}).then(function(results) { | ||||||
|                     if (results.join(" ") !== timeouts.join(" ")) { | 				if (results.join(' ') !== timeouts.join(' ')) { | ||||||
|                         console.error(results); | 					console.error(results); | ||||||
|                         throw new Error("sync result set out-of-order"); | 					throw new Error('sync result set out-of-order'); | ||||||
|                     } | 				} | ||||||
|                     console.info("Handled sync tasks correctly."); | 				console.info('Handled sync tasks correctly.'); | ||||||
|                 }); | 			}); | ||||||
|             }) | 		}) | ||||||
|             .then(function() { | 		.then(function() { | ||||||
|                 return batchAsync(4, tasks, function(task) { | 			return batchAsync(4, tasks, function(task) { | ||||||
|                     if (0 === Math.floor(Math.random() * 2) % 2) { | 				if (0 === Math.floor(Math.random() * 2) % 2) { | ||||||
|                         throw new Error("any async error will do"); | 					throw new Error('any async error will do'); | ||||||
|                     } | 				} | ||||||
|                     return task(); | 				return task(); | ||||||
|                 }) | 			}) | ||||||
|                     .then(function(results) { | 				.then(function(results) { | ||||||
|                         console.log(results); | 					console.log(results); | ||||||
|                         var e = new Error("async rejection should not pass!"); | 					var e = new Error('async rejection should not pass!'); | ||||||
|                         e.FAIL = true; | 					e.FAIL = true; | ||||||
|                         throw e; | 					throw e; | ||||||
|                     }) | 				}) | ||||||
|                     .catch(function(e) { | 				.catch(function(e) { | ||||||
|                         if (e.FAIL) { | 					if (e.FAIL) { | ||||||
|                             throw e; | 						throw e; | ||||||
|                         } | 					} | ||||||
|                         console.info("Pass: Exception thrown when expected"); | 					console.info('Pass: Exception thrown when expected'); | ||||||
|                     }); | 				}); | ||||||
|             }) | 		}) | ||||||
|             .then(function() { | 		.then(function() { | ||||||
|                 return batchAsync(4, timeouts, function() { | 			return batchAsync(4, timeouts, function() { | ||||||
|                     if (0 === Math.floor(Math.random() * 2) % 2) { | 				if (0 === Math.floor(Math.random() * 2) % 2) { | ||||||
|                         throw new Error("any sync error will do"); | 					throw new Error('any sync error will do'); | ||||||
|                     } | 				} | ||||||
|                     return null; |         return null; | ||||||
|                 }) | 			}) | ||||||
|                     .then(function(/*results*/) { | 				.then(function(results) { | ||||||
|                         var e = new Error("should not pass sync exception!"); | 					var e = new Error('should not pass sync exception!'); | ||||||
|                         e.FAIL = true; | 					e.FAIL = true; | ||||||
|                         throw e; | 					throw e; | ||||||
|                     }) | 				}) | ||||||
|                     .catch(function(e) { | 				.catch(function(e) { | ||||||
|                         if (e.FAIL) { | 					if (e.FAIL) { | ||||||
|                             throw e; | 						throw e; | ||||||
|                         } | 					} | ||||||
|                     }) | 				}) | ||||||
|                     .then(function() { | 				.then(function() { | ||||||
|                         // wait for the tasks the error left dangling to print their message
 | 					// wait for the tasks the error left dangling to print their message
 | ||||||
|                         console.info("Pass: Promise rejected when expected"); | 					console.info('Pass: Promise rejected when expected'); | ||||||
|                         return promiseTimeout(1000); | 					return promiseTimeout(1000); | ||||||
|                     }); | 				}); | ||||||
|             }); | 		}); | ||||||
|     } | } | ||||||
| 
 | 
 | ||||||
|     function promiseTimeout(timeout) { | function promiseTimeout(timeout) { | ||||||
|         return new Promise(function(resolve) { | 	return new Promise(function(resolve, reject) { | ||||||
|             setTimeout(resolve, timeout); | 		setTimeout(resolve, timeout); | ||||||
|         }); | 	}); | ||||||
|     } | } | ||||||
| 
 | 
 | ||||||
|     testBatch() | testBatch() | ||||||
|         .then(function() { | 	.then(function() { | ||||||
|             console.info("PROBABLY PASSED"); | 		console.info('PROBABLY PASSED'); | ||||||
|             console.info( | 		console.info( | ||||||
|                 "We tested what could be tested. Do the results make sense?" | 			'We tested what could be tested without knowing Passed what could be tested Do the results make sense?' | ||||||
|             ); | 		); | ||||||
|         }) | 	}) | ||||||
|         .catch(function(e) { | 	.catch(function(e) { | ||||||
|             console.error("FAIL!"); | 		console.error('FAIL!'); | ||||||
|             console.error(e); | 		console.error(e); | ||||||
|             process.exit(500); |     process.exit(500); | ||||||
|         }); | 	}); | ||||||
| })("undefined" !== typeof window ? window : module.exports); | 
 | ||||||
|  | }('undefined' !== typeof window ? window : module.exports)); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user