oxjs/source/Ox/js/Async.js

245 lines
8.8 KiB
JavaScript
Raw Normal View History

2012-05-24 06:54:44 +00:00
'use strict';
2012-05-23 15:43:01 +00:00
(function() {
2012-05-25 07:40:27 +00:00
function asyncMap(forEach, collection, iterator, that, callback) {
var type = Ox.typeOf(collection),
2012-05-23 15:43:01 +00:00
results = type == 'object' ? {} : [];
callback = Ox.last(arguments);
that = arguments.length == 5 ? that : null;
2012-05-25 07:40:27 +00:00
forEach(collection, function(value, key, collection, callback) {
iterator(value, key, collection, function(value) {
results[key] = value;
2012-05-23 15:43:01 +00:00
callback();
});
}, that, function() {
callback(type == 'string' ? results.join('') : results);
});
};
2012-05-25 07:40:27 +00:00
Ox.asyncMap = function(array, iterator, that, callback) {
array = Ox.makeArray(array);
2012-05-23 15:43:01 +00:00
callback = Ox.last(arguments);
that = arguments.length == 4 ? that : null;
2012-05-25 07:40:27 +00:00
if (array.some(Ox.isArray)) {
Ox.serialMap(array, function(value, key, array, callback) {
Ox.parallelMap(Ox.makeArray(value), iterator, callback);
2012-05-23 15:43:01 +00:00
}, callback);
} else {
2012-05-25 07:40:27 +00:00
Ox.parallelMap(array, iterator, callback);
2012-05-23 15:43:01 +00:00
}
};
/*@
2012-05-23 16:14:36 +00:00
Ox.nonblockingForEach <f> Non-blocking forEach with synchronous iterator
2012-05-23 15:43:01 +00:00
(col, iterator[, that], callback[, ms]) -> <u> undefined
@*/
2012-05-25 07:40:27 +00:00
Ox.nonblockingForEach = function(collection, iterator, that, callback, ms) {
var i = 0, keys, last = Ox.last(arguments),
n, time, type = Ox.typeOf(collection);
2012-05-23 15:43:01 +00:00
callback = Ox.isFunction(last) ? last : arguments[arguments.length - 2];
2012-05-25 07:40:27 +00:00
collection = type == 'array' || type == 'object'
? collection : Ox.toArray(collection);
keys = type == 'object'
? Object.keys(collection) : Ox.range(collection.length);
2012-05-23 15:43:01 +00:00
ms = ms || 1000;
2012-05-25 07:40:27 +00:00
n = Ox.len(collection);
2012-05-23 15:43:01 +00:00
that = arguments.length == 5 || (
arguments.length == 4 && Ox.isFunction(last)
) ? that : null;
2012-05-23 15:48:17 +00:00
time = +new Date();
2012-05-23 15:43:01 +00:00
iterate();
function iterate() {
2012-05-24 06:54:44 +00:00
Ox.forEach(keys.slice(i), function(key) {
2012-05-25 07:40:27 +00:00
if (key in collection) {
2012-05-24 06:54:44 +00:00
try {
2012-05-25 07:40:27 +00:00
iterator.call(that, collection[key], key, collection);
2012-05-25 09:44:25 +00:00
} catch (error) {
2012-05-25 07:40:27 +00:00
if (error === Ox.BreakError) {
2012-05-24 06:54:44 +00:00
i = n;
}
2012-05-25 09:44:25 +00:00
throw error;
2012-05-24 06:54:44 +00:00
}
2012-05-23 15:43:01 +00:00
}
2012-05-24 06:54:44 +00:00
i++;
2012-05-25 07:40:27 +00:00
+new Date() >= time + ms && Ox.Break();
2012-05-24 06:54:44 +00:00
});
if (i < n) {
setTimeout(function() {
time = +new Date();
iterate();
}, 1);
2012-05-23 16:14:36 +00:00
} else {
callback();
}
2012-05-23 15:43:01 +00:00
}
};
2012-05-23 16:14:36 +00:00
/*@
Ox.nonblockingMap <f> Non-blocking map with synchronous iterator
2012-05-25 07:40:27 +00:00
(collection, iterator[, that]) -> <u> undefined
collection <a|o|s> Collection
2012-05-23 16:14:36 +00:00
iterator <f> Iterator function
that <o> The iterator's this binding
callback <f> Callback function
<script>
var time = +new Date();
2012-05-24 06:54:44 +00:00
Ox.nonblockingMap(
Ox.range(1000000),
function (value, index, array) {
return +new Date() - time;
2012-05-23 16:14:36 +00:00
},
function(results) {
2012-05-24 06:54:44 +00:00
Ox.print(results.length);
},
1000
2012-05-23 16:14:36 +00:00
);
</script>
> Ox.nonblockingMap(Ox.range(100000), Ox.identity, function(r) { Ox.test(r.length, 100000); })
2012-05-27 16:44:00 +00:00
undefined
2012-05-23 16:14:36 +00:00
@*/
2012-05-25 07:40:27 +00:00
Ox.nonblockingMap = function(collection, iterator, that, callback, ms) {
2012-05-24 06:54:44 +00:00
var last = Ox.last(arguments),
2012-05-25 07:40:27 +00:00
type = Ox.typeOf(collection),
2012-05-24 06:54:44 +00:00
results = type == 'object' ? {} : [];
callback = Ox.isFunction(last) ? last : arguments[arguments.length - 2];
that = arguments.length == 5 || (
arguments.length == 4 && Ox.isFunction(last)
) ? that : null;
2012-05-25 07:40:27 +00:00
Ox.nonblockingForEach(collection, function(value, key, collection) {
results[key] = iterator.call(that, value, key, collection);
2012-05-24 06:54:44 +00:00
}, function() {
callback(type == 'string' ? results.join('') : results);
}, ms);
2012-05-23 15:43:01 +00:00
};
/*@
Ox.parallelForEach <f> forEach with asynchronous iterator, running in parallel
2012-05-25 07:40:27 +00:00
(collection, iterator[, that], callback) -> <u> undefined
collection <a|o|s> Collection
2012-05-23 15:43:01 +00:00
iterator <f> Iterator function
2012-05-25 07:40:27 +00:00
value <*> Value
2012-05-23 15:43:01 +00:00
key <n|s> Key
2012-05-25 07:40:27 +00:00
collection <a|o|s> The collection
2012-05-23 15:43:01 +00:00
callback <f> Callback function
that <o> The iterator's this binding
callback <f> Callback function
@*/
2012-05-25 07:40:27 +00:00
Ox.parallelForEach = function(collection, iterator, that, callback) {
var i = 0, n, type = Ox.typeOf(collection);
2012-05-23 15:43:01 +00:00
callback = Ox.last(arguments);
2012-05-25 07:40:27 +00:00
collection = type == 'array' || type == 'object'
? collection : Ox.toArray(collection);
n = Ox.len(collection);
2012-05-23 15:43:01 +00:00
that = arguments.length == 4 ? that : null;
2012-05-25 07:40:27 +00:00
Ox.forEach(collection, function(value, key, collection) {
iterator.call(that, value, key, collection, function() {
2012-05-23 15:43:01 +00:00
++i == n && callback();
});
});
};
/*@
Ox.parallelMap <f> Parallel map with asynchronous iterator
2012-05-25 07:40:27 +00:00
(collection, iterator[, that], callback) -> <u> undefined
collection <a|o|s> Collection
2012-05-23 15:43:01 +00:00
iterator <f> Iterator function
2012-05-25 07:40:27 +00:00
value <*> Value
2012-05-23 15:43:01 +00:00
key <n|s> Key
2012-05-25 07:40:27 +00:00
collection <a|o|s> The collection
2012-05-23 15:43:01 +00:00
callback <f> Callback function
that <o> The iterator's this binding
callback <f> Callback function
results <a|o|s> Results
<script>
var time = +new Date();
Ox.parallelMap(
Ox.range(10),
function (value, index, array, callback) {
setTimeout(function() {
callback(+new Date() - time);
}, Ox.random(1000));
},
function(results) {
Ox.print(results);
}
);
</script>
> Ox.parallelMap(Ox.range(100000), Ox.noop, function(r) { Ox.test(r.length, 100000); })
2012-05-27 16:44:00 +00:00
undefined
2012-05-23 15:43:01 +00:00
@*/
Ox.parallelMap = function() {
asyncMap.apply(null, [Ox.parallelForEach].concat(Ox.toArray(arguments)));
};
/*@
Ox.serialForEach <f> forEach with asynchronous iterator, run serially
2012-05-25 07:40:27 +00:00
(collection, iterator[, that], callback) -> <u> undefined
collection <a|o|s> Collection
2012-05-23 15:43:01 +00:00
iterator <f> Iterator function
2012-05-25 07:40:27 +00:00
value <*> Value
2012-05-23 15:43:01 +00:00
key <n|s> Key
2012-05-25 07:40:27 +00:00
collection <a|o|s> The collection
2012-05-23 15:43:01 +00:00
callback <f> Callback function
that <o> The iterator's this binding
callback <f> Callback function
@*/
2012-05-25 07:40:27 +00:00
Ox.serialForEach = function(collection, iterator, that, callback) {
var i = 0, keys, n, type = Ox.typeOf(collection);
2012-05-23 15:43:01 +00:00
callback = Ox.last(arguments);
2012-05-25 07:40:27 +00:00
collection = type == 'array' || type == 'object'
? collection : Ox.toArray(collection);
keys = type == 'object'
? Object.keys(collection) : Ox.range(collection.length);
n = Ox.len(collection);
2012-05-23 15:43:01 +00:00
that = arguments.length == 4 ? that : null;
iterate();
function iterate() {
2012-05-25 07:40:27 +00:00
keys[i] in collection && iterator.call(
that,
collection[keys[i]],
keys[i],
collection,
function() {
++i < n ? iterate() : callback();
}
);
2012-05-23 15:43:01 +00:00
}
};
/*@
Ox.serialMap <f> Serial map with asynchronous iterator
2012-05-25 07:40:27 +00:00
(collection, iterator[, that], callback) -> <u> undefined
collection <a|o|s> Collection
2012-05-23 15:43:01 +00:00
iterator <f> Iterator function
2012-05-25 07:40:27 +00:00
value <*> Value
2012-05-23 15:43:01 +00:00
key <n|s> Key
2012-05-25 07:40:27 +00:00
collection <a|o|s> The collection
2012-05-23 15:43:01 +00:00
callback <f> Callback function
that <o> The iterator's this binding
callback <f> Callback function
2012-05-25 07:40:27 +00:00
results <a|o|s> Results
2012-05-23 15:43:01 +00:00
<script>
var time = +new Date();
Ox.serialMap(
Ox.range(10),
function (value, index, array, callback) {
setTimeout(function() {
callback(+new Date() - time);
}, Ox.random(1000));
},
function(results) {
Ox.print(results);
}
);
</script>
2012-05-27 16:44:00 +00:00
> Ox.serialMap(Ox.range(1000), Ox.noop, function(r) { Ox.test(r.length, 1000); })
undefined
2012-05-23 15:43:01 +00:00
@*/
2012-05-25 07:40:27 +00:00
Ox.serialMap = function(collection, iterator, that, callback) {
2012-05-23 15:43:01 +00:00
asyncMap.apply(null, [Ox.serialForEach].concat(Ox.toArray(arguments)));
};
2012-05-27 16:44:00 +00:00
// FIXME: The above test with 10000 iterations blows the stack
2012-05-23 15:43:01 +00:00
}());