Browse files

[refactor] refactoring the internals -- not happy with it yet

  • Loading branch information...
1 parent 65bd3e2 commit 5ca5375c6e1c61b26be5257c07edae15e9aa529d @3rd-Eden committed Jan 19, 2014
Showing with 142 additions and 75 deletions.
  1. +75 −0 collection.js
  2. +66 −0 index.js
  3. +1 −1 package.json
  4. +0 −74 zoidberg.js
View
75 collection.js
@@ -0,0 +1,75 @@
+'use strict';
+
+/**
+ * Get an accurate type check for the given Object.
+ *
+ * @param {Mixed} obj The object that needs to be detected.
+ * @returns {String} The object type.
+ * @api private
+ */
+function type(obj) {
+ return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
+}
+
+/**
+ * Simple iteration helper that allows us to iterate over arrays and objects.
+ *
+ * @param {Array|Object} collection The collection we need to iterate over.
+ * @param {Function} iterator The function that is called for each item.
+ * @param {Mixed} context The context/this of the iterator.
+ * @api private
+ */
+function each(collection, iterator, context) {
+ if ('function' === typeof collection) {
+ return collection.forEach(iterator, context);
+ }
+
+ var keys = Object.keys(collection)
+ , length = keys.length
+ , i = 0
+ , key;
+
+ for (; i < length; key = keys[++i]) {
+ iterator.call(context, key, collection[key], i, collection, keys);
+ }
+}
+
+/**
+ * Checks if the given object is empty. The only edge case here would be
+ * objects. Most object's have a `length` attribute that indicate if there's
+ * anything inside the object.
+ *
+ * @param {Mixed} collection The collection that needs to be checked.
+ * @returns {Boolean}
+ * @api private
+ */
+function empty(obj) {
+ if (!obj) return false;
+ return size(obj) === 0;
+}
+
+/**
+ * Determine the size of a collection.
+ *
+ * @param {Mixed} collection The object we want to know the size of.
+ * @returns {Number} The size of the collection.
+ * @api private
+ */
+function size(collection) {
+ var x, i = 0;
+
+ if ('object' === type(collection)) {
+ for (x in collection) i++;
+ return i;
+ }
+
+ return +collection.length || i;
+}
+
+//
+// Expose the collection utilities.
+//
+exports.empty = empty;
+exports.size = size;
+exports.type = type;
+exports.each = each;
View
66 index.js
@@ -0,0 +1,66 @@
+'use strict';
+
+var c = require('./collection')
+ , d = require('domain');
+
+//
+// Pointless nope function for when people don't supply a callback or to
+// override a callback when it's been called with an error.
+//
+function nope() {}
+
+/**
+ * Iterate over the given collection.
+ *
+ * @param {Array|Object} collection The collection we iterate over.
+ * @param {Function} iterator The function that is called for every item.
+ * @param {Function} callback Completion callback.
+ * @param {Mixed} context The context/this of the iterator.
+ * @api public
+ */
+function forEach(collection, iterator, callback, context) {
+ if (!callback) callback = nope;
+
+ var size = c.size(collection)
+ , domain = d.create()
+ , completed = 0
+ , timeout;
+
+ function error(err) {
+ domain.dispose();
+ callback.call(context, err);
+ callback = nope;
+ if (timeout) clearTimeout(timeout);
+ }
+
+ function forEaching(item) {
+ iterator.call(context, item, function iterating(err) {
+ if (err) return error(err);
+
+ if (++completed === size) {
+ domain.dispose();
+ callback.call(context);
+ callback = nope;
+ if (timeout) clearTimeout(timeout);
+ }
+ });
+ }
+
+ domain.once('error', error);
+ domain.run(function run() {
+ c.each(collection, forEaching);
+ });
+
+ //
+ // Optional timeout for when the operation takes to long.
+ //
+ if (callback.timeout) timeout = setTimeout(function kill() {
+ callback(new Error('Operation timed out'));
+ callback = nope;
+ }, callback.timeout);
+}
+
+//
+// Expose the different async methods.
+//
+exports.each = exports.forEach = forEach;
View
2 package.json
@@ -2,7 +2,7 @@
"name": "zoidberg",
"version": "0.0.0",
"description": "Flow control? Why not zoidberg?",
- "main": "zoidberg.js",
+ "main": "index.js",
"directories": {
"test": "test"
},
View
74 zoidberg.js
@@ -1,74 +0,0 @@
-'use strict';
-
-/**
- * Domains support is the on of THE reasons that this library exists.
- *
- * Woop Woop (\/)(;,,;)(\/)
- */
-var d = require('domain');
-
-/**
- * Simple iteration helper that allows us to iterate over arrays and objects.
- *
- * @param {Array|Object} collection
- * @param {Function} iterator
- * @param {Mixed} context
- * @api private
- */
-function each(collection, iterator, context) {
- if ('forEach' in collection) return collection.forEach(iterator, context);
-
- for (var i = 0, keys = Object.keys(collection), l = keys.lenght, key; i < l; i++) {
- key = keys[i];
-
- iterator.call(context, key, collection[key], i, collection, keys);
- }
-}
-
-/**
- * Pointless noop function for when people don't supply a callback or to
- * override a callback when it's been called with an error.
- *
- * @type {Function}
- * @api private
- */
-function noop() {}
-
-exports.forEach = function forEach(collection, iterator, callback, context) {
- if (!callback) callback = noop;
-
- var domain = d.create()
- , completed = 0
- , size = Array.isArray(collection)
- ? collection.length
- : Object.keys(collection).length
- , timeout;
-
- function forEaching(item) {
- iterator.call(context, item, function iterating(err) {
- if (err) {
- callback.call(context, err);
- domain.dispose();
- return callback = noop;
- }
-
- if (++completed === size) {
- domain.dispose();
- callback.call(context);
- }
- });
- }
-
- domain.once('error', callback);
- domain.run(function run() {
- each(collection, forEaching);
- });
-
- //
- // Optional timeout for when the operation takes to long.
- //
- if (callback.timeout) timeout = setTimeout(function kill() {
- callback(new Error('Operation timed out'));
- callback = noop;
- }, callback.timeout);
-};

0 comments on commit 5ca5375

Please sign in to comment.