Skip to content

Instantly share code, notes, and snippets.

@blindman2k
Last active February 27, 2016 09:45
Show Gist options
  • Save blindman2k/c886c6014e9372e0314b to your computer and use it in GitHub Desktop.
Save blindman2k/c886c6014e9372e0314b to your computer and use it in GitHub Desktop.
Async - Library based on https://github.com/caolan/async

Async 0.0.1 (beta!)

Based on Caolan McMahon's Async code.

Still to do ...

  • Documentation
  • Split into multiple classes to reduce the size if you don't want all of the library
  • Fix up all bindings (bindenv). Currently they are all over the place.
  • More tests

Might be convinced to implement ...

  • log, retry

Not implement unless someone desperately needs ...

  • All *Limit functions
  • apply, queue, priorityQueue, cargo, auto, memoize, unmemoize

License

This class is licensed under the MIT License.

// Copyright (c) 2016 Electric Imp
// This file is licensed under the MIT License
// http://opensource.org/licenses/MIT
// From: https://github.com/caolan/async
class async {
/*********[ Collections ]*********/
// each: Applies the function iteratee to each item in arr, in parallel.
// related: eachLimit
static function each(arr, iterator, callback = null) {
return _eachOf(arr, _withoutIndex(iterator), callback);
}
// eachSeries: Applies the function iteratee to each item in arr, in series.
static function eachSeries(arr, iterator, callback = null) {
return eachOfSeries(arr, _withoutIndex(iterator), callback);
}
// forEachOf: Like each, except that it iterates over objects, and passes the key as the second argument to the iteratee.
// related: forEachOfLimit
static function forEachOf(obj, iterator, callback = null) {
return _eachOf(obj, iterator, callback);
}
// forEachOf: Like each, except that it iterates over objects, and passes the key as the second argument to the iteratee.
static function forEachOfSeries(obj, iterator, callback = null) {
return _eachOfSeries(obj, iterator, callback);
}
// map: Produces a new array of values by mapping each value in arr through the iteratee function.
// related: mapLimit
static function map(arr, iterator, callback = null) {
return _doParallel(_map)(arr, iterator, callback);
}
// mapSeries: Produces a new array of values by mapping each value in arr through the iteratee function.
static function mapSeries(arr, iterator, callback = null) {
return _doSeries(_map)(arr, iterator, callback);
}
// filter: Returns a new array of all the values in arr which pass an async truth test
// related: filterLimit
// aliases: select
static function filter(arr, iterator, callback = null) {
return _doParallel(_filter)(arr, iterator, callback);
}
// filterSeries: Returns a new array of all the values in arr which pass an async truth test
static function filterSeries(arr, iterator, callback = null) {
return _doSeries(_filter)(arr, iterator, callback);
}
// reject: The opposite of filter. Removes values that pass an async truth test.
// related: rejectLimit
static function reject(arr, iterator, callback = null) {
return _doParallel(_reject)(arr, iterator, callback);
}
// rejectSeries: The opposite of filter. Removes values that pass an async truth test.
static function rejectSeries(arr, iterator, callback = null) {
return _doSeries(_reject)(arr, iterator, callback);
}
// reduce: Reduces arr into a single value using an async iteratee to return each successive step. memo is the initial state of the reduction.
// aliases: inject, foldl
static function reduce(arr, memo, iterator, callback) {
_eachOfSeries(arr, function(x, i, callback) {
iterator(memo, x, function(err, v) {
memo = v;
callback(err);
});
}.bindenv(this), function(err) {
callback(err, memo);
}.bindenv(this));
}
// reduceRight: Same as reduce, only operates on arr in reverse order.
// aliases: foldr
static function reduceRight(arr, memo, iterator, callback = null) {
arr.reverse();
return reduce(arr, memo, iterator, callback);
}
// detect: Returns the first value in arr that passes an async truth test.
// related: detectLimit
static function detect(arr, iterator, callback = null) {
return _createTester(_eachOf, _identity, _findGetResult)(arr, null, iterator, callback);
}
// detect: Returns the first value in arr that passes an async truth test.
static function detectSeries(arr, iterator, callback = null) {
return _createTester(_eachOfSeries, _identity, _findGetResult)(arr, null, iterator, callback);
}
// some: Returns true if at least one element in the arr satisfies an async test. If any iteratee call returns true, the main callback is immediately called.
// related: someLimit
// aliases: any
static function some(arr, iterator, callback = null) {
return _createTester(_eachOf, _boolean, _identity)(arr, null, iterator, callback);
}
// every: Returns true if every element in arr satisfies an async test. If any iteratee call returns false, the main callback is immediately called.
// related: everyLimit
// aliases: all
static function every(arr, iterator, callback = null) {
return _createTester(_eachOf, _notId, _notId)(arr, null, iterator, callback);
}
// concat: Applies iteratee to each item in arr, concatenating the results. Returns the concatenated list.
static function concat(arr, iterator, callback = null) {
return _doParallel(_concat)(arr, iterator, callback);
}
// concatSeries: Applies iteratee to each item in arr, concatenating the results. Returns the concatenated list.
static function concatSeries(arr, iterator, callback = null) {
return _doSeries(_concat)(arr, iterator, callback);
}
// sortBy: Sorts a list by the results of running each arr value through an async iteratee.
static function sortBy(arr, iterator, callback = null) {
function comparator(left, right) {
local a = left.criteria, b = right.criteria;
return a < b ? -1 : a > b ? 1 : 0;
}
map(arr, function(x, cb) {
iterator(x, function(err, criteria) {
if (err) return cb(err);
cb(null, {"value": x, "criteria": criteria});
});
}.bindenv(this), function(err, results) {
if (err) return cb(err);
results.sort(comparator);
callback(null, _arrayMap(results, _property("value")));
}.bindenv(this));
}
/*********[ Control Flow ]*********/
// series: Run the functions in the tasks array in series, each one running once the previous function has completed.
static function series(tasks, callback = null) {
return _parallel(_eachOfSeries, tasks, callback);
}
// parallel: Run the tasks array of functions in parallel, without waiting until the previous function has completed.
// related: parallelLimit
static function parallel(tasks, callback = null) {
return _parallel(_eachOf, tasks, callback);
}
// whilst: Repeatedly call fn, while test returns true. Calls callback when stopped, or an error occurs.
// related: doWhilst
static function whilst(test, iterator, callback = null) {
callback = callback || _noop;
if (!test()) return callback(null);
local next;
next = _rest(function(err, args) {
if (err) return callback(err);
if (test()) return iterator(next);
args.insert(0, this);
args.insert(1, null);
callback.acall(args);
});
iterator(next);
}
// until: Repeatedly call fn until test returns true. The inverse of whilst.
// related: doUntil
static function until(test, iterator, callback = null) {
return whilst(function() {
if (vargv.len() == 0 || vargv[0] != this) vargv.insert(0, this);
return !test.acall(vargv);
}, iterator, callback);
}
// during: Like whilst, except the test is an asynchronous function that is passed a callback in the form of function(err, truth).
// related: doDuring
static function during(test, iterator, callback = null) {
callback = callback || _noop;
local next, check;
next = _rest(function(err, args) {
if (err) return callback(err);
test(check);
});
check = function(err, truth) {
if (err) return callback(err);
if (!truth) return callback(null);
iterator(next);
};
test(check);
}
// forever: Calls the asynchronous function fn with a callback parameter that allows it to call itself again, in series, indefinitely.
static function forever(iterator, errback = null) {
local done = _once(errback || _noop);
local task = ensureAsync(iterator);
local next;
next = function(err = null) {
if (err) return done(err);
task(next);
}
next();
}
// waterfall: Runs the tasks array of functions in series, each passing their results to the next in the array.
static function waterfall(tasks, callback = null) {
callback = _once(callback || _noop);
if (!tasks.len()) return callback();
local wrapIterator;
wrapIterator = function(iterator) {
return _rest(function(err, args) {
args.insert(0, this);
if (err) {
args.insert(1, err);
callback.acall(args);
} else {
local next = iterator.next();
if (next) {
args.push(wrapIterator(next));
} else {
args.push(callback);
}
ensureAsync(iterator.fn).acall(args);
}
});
}
wrapIterator(iterator(tasks))();
}
// compose: Creates a function which is a composition of the passed asynchronous functions. Each function consumes the return value of the function that follows.
static function compose(...) {
vargv.reverse();
vargv.insert(0, this);
return seq.acall(vargv);
}
// seq: Version of the compose function that is more natural to read. Each function consumes the return value of the previous function.
static function seq(...) {
local fns = vargv;
return function(...) {
local args = vargv;
local cb = args.len() > 0 ? args[args.len() - 1] : null;
if (typeof cb == "function") {
args.pop();
} else {
cb = _noop;
}
reduce(fns, args,
function(newargs, fn, cb) {
local next = _rest(function(err, nextargs) {
cb(err, nextargs);
})
newargs.insert(0, this);
newargs.push(next);
fn.acall(newargs);
}.bindenv(this),
function(err, results) {
results.insert(0, this);
results.insert(1, err);
cb.acall(results);
}.bindenv(this)
);
}.bindenv(this);
}
// applyEach: Applies the provided arguments to each function in the array, calling callback after all functions have completed.
// related: applyEachSeries
static function applyEach(...) {
vargv.insert(0, this);
return _applyEach(_eachOf).acall(vargv);
}
/*********[ Utils ]*********/
// nextTick: Calls callback on a later loop around the event loop.
// aliases: setImmediate
static function nextTick(callback) {
imp.wakeup(0, callback);
}
// ensureAsync: Wrap an async function and ensure it calls its callback on a later tick of the event loop.
static function ensureAsync(callback) {
return function(...) {
vargv.insert(0, this);
imp.wakeup(0, function() {
callback.acall(vargv);
});
}
}
// asyncify: Take a sync function and make it async, passing its return value to a callback. Handles Promises too.
static function asyncify(fn) {
return function(...) {
local args = vargv;
local callback = args.pop();
local result;
try {
args.insert(0, this);
result = fn.acall(args);
} catch (e) {
return callback(e);
}
if ("then" in result && typeof result.then == "function") {
// if result is Promise object
result.then(function(res) {
callback(null, res);
}, function(err) {
callback(err);
});
} else {
callback(null, result);
}
}
}
// iterator: Creates an iterator function which calls the next function in the tasks array, returning a continuation to call the next one after that.
static function iterator(tasks) {
local makeCallback;
makeCallback = function(index) {
local cb = {}
cb.fn <- function(...) {
if (tasks.len()) {
vargv.insert(0, this);
tasks[index].acall(vargv);
}
return cb.next();
}
cb.next <- function() {
return (index < tasks.len() - 1) ? makeCallback(index + 1) : null;
};
return cb;
}
return makeCallback(0);
}
// times: Calls the iteratee function n times, and accumulates results in the same manner you would use with map.
// related: timesSeries, timesLimit
static function times(count, iterator, callback = null) {
map(_range(0, count, 1), iterator, callback);
}
// constant: Returns a function that when called, calls-back with the values provided.
static function constant(...) {
local args = vargv;
args.insert(0, this);
args.insert(1, null);
return function (cb) {
return cb.acall(args);
};
}
/*********[ Unsupported ]*********/
/*
// apply: Creates a continuation function with some arguments already applied.
static function apply(fn, ...) {
}
// queue: Creates a queue object with the specified concurrency. Tasks added to the queue are processed in parallel (up to the concurrency limit).
static function queue(worker, concurrency = 1) {
}
// priorityQueue: The same as queue only tasks are assigned a priority and completed in ascending priority order.
static function priorityQueue(worker, concurrency) {
}
// cargo: The same as queue only tasks are assigned a priority and completed in ascending priority order.
static function cargo(worker, payload = null) {
}
// auto: Determines the best order for running the functions in tasks, based on their requirements.
static function auto(tasks, concurrency = null, callback = null) {
}
// log: Logs the result of an async function to the console.
// related: dir
static function log(fn, ...) {
}
// retry: Attempts to get a successful response from task no more than times times before returning an error.
static function retry(opts, task, callback = null) {
}
// memoize
// unmemoize
*/
/*********[ Internal ]*********/
static function _eachOf(object, iterator, callback = null) {
local callback = _once(callback || _noop);
local object = object || {};
local completed = 0, key = null;
function done(err = null) {
completed--;
// Check key is null in case iterator isn't exhausted and done resolved synchronously.
if (err) {
callback(err);
} else if (key == null && completed <= 0) {
callback(null);
}
}
foreach (_key,val in object) {
key = _key; // Copy to the larger scoped key
completed++;
iterator(val, key, _once(done));
}
key = null;
if (completed == 0) callback(null);
}
static function _eachOfSeries(obj, iterator, callback) {
local callback = _once(callback || _noop);
local obj = obj || [];
local nextKey = _keyIterator(obj);
local key = nextKey();
local iterate;
iterate = function() {
local sync = true;
if (key == null) {
return callback(null);
}
iterator(obj[key], key, _once(function(err = null) {
if (err) {
callback(err);
} else {
key = nextKey();
if (key == null) {
return callback(null);
} else {
if (sync) {
nextTick(iterate);
} else {
iterate();
}
}
}
}));
sync = false;
}.bindenv(this);
iterate();
}
static function _applyEach(eachfn) {
return function(fns, ...) {
local go = function(...) {
local args = vargv;
local callback = args.len() > 0 ? args.pop() : null;
if (typeof callback != "function") {
callback = _noop;
}
args.insert(0, this);
args.push(null);
return eachfn( fns,
function (fn, _, cb) {
args[args.len() - 1] = cb;
fn.acall(args);
},
callback
);
};
if (vargv.len()) {
vargv.insert(0, this);
return go.acall(vargv);
} else {
return go;
}
}
}
static function _before(n, fn) {
local result = null;
return function(...) {
if (--n > 0) {
vargv.insert(0, this);
result = fn.acall(vargv);
}
if (n <= 1) {
fn = null;
}
return result;
}
}
static function _once(fn) {
return _before(2, fn)
}
static function _noop(...) {
return null;
}
static function _withoutIndex(iterator) {
return function(value, index, callback) {
return iterator(value, callback);
}
}
static function _doParallel(fn) {
return function(obj, iterator, callback) {
return fn(_eachOf, obj, iterator, callback);
}
}
static function _doSeries(fn) {
return function (obj, iterator, callback) {
return fn(_eachOfSeries, obj, iterator, callback);
};
}
static function _map(eachfn, arr, iterator, callback) {
local callback = _once(callback || _noop);
local arr = arr || [];
local results = (typeof arr == "array") ? array(arr.len()) : {};
eachfn(arr, function(value, index, callback) {
iterator(value, function(err, v) {
if (typeof results == "array") {
results[index] = v;
} else {
results[index] <- v;
}
callback(err);
});
}.bindenv(this), function(err) {
callback(err, results);
}.bindenv(this));
}
static function _filter(eachfn, arr, iterator, callback) {
local results = [];
eachfn(arr, function(x, index, callback) {
iterator(x, function(err, v) {
if (err) {
callback(err);
} else {
if (v) {
results.push({"index": index, "value": x});
}
callback();
}
});
}.bindenv(this), function(err) {
if (err) {
callback(err);
} else {
results.sort(function(a, b) {
return a.index - b.index;
})
callback(null, _arrayMap(results, _property("value")));
}
}.bindenv(this));
}
static function _reject(eachfn, arr, iterator, callback) {
_filter(eachfn, arr, function(value, cb) {
iterator(value, function(err, v) {
if (err) {
cb(err);
} else {
cb(null, !v);
}
}.bindenv(this));
}.bindenv(this), callback);
}
static function _arrayMap(arr, iteratee) {
local result = array(arr.len());
foreach (key,val in arr) {
result[key] = iteratee(val);
}
return result;
}
static function _concat(eachfn, arr, fn, callback) {
local result = [];
eachfn(arr, function(x, index, cb) {
fn(x, function(err, y) {
result.extend(y || []);
cb(err);
});
}.bindenv(this), function(err) {
callback(err, result);
}.bindenv(this));
}
static function _parallel(eachfn, tasks, callback) {
callback = callback || _noop;
local results = (typeof tasks == "array") ? array(tasks.len()) : {};
eachfn(tasks, function(task, key, callback) {
task(_rest(function(err = null, args = null) {
if (args.len() == 0) args = null;
else if (args.len() == 1) args = args[0];
if (typeof results == "array") {
results[key] = args;
} else {
results[key] <- args;
}
callback(err);
}));
}.bindenv(this), function(err) {
callback(err, results);
}.bindenv(this));
}
static function _property(key) {
return function(object) {
return (object == null) || !(key in object) ? null : object[key];
};
}
static function _identity(obj, ...) {
return obj;
}
static function _boolean(val, ...) {
return !!val;
}
static function _notId(val, ...) {
return !val;
}
static function _findGetResult(v, x) {
return x;
}
static function _nativeMax(a, b) {
return a > b ? a : b;
}
static function _keys(obj) {
local results = [];
foreach (key, val in obj) {
results.push(key);
}
return results;
}
static function _keyIterator(coll) {
local i = -1;
local len;
if (typeof coll == "array") {
len = coll.len();
return function /* next */ () {
i++;
return i < len ? i : null;
};
} else {
local okeys = _keys(coll);
len = okeys.len();
return function /* next */ () {
i++;
return i < len ? okeys[i] : null;
};
}
}
static function _createTester(eachfn, check, getResult) {
return function(arr, limit, iterator, cb) {
function done(err) {
if (cb) {
if (err) {
cb(err);
} else {
cb(null, getResult(false, null));
}
}
}
function iteratee(x, _, callback) {
if (!cb) return callback();
iterator(x, function(err, v) {
if (cb) {
if (err) {
cb(err);
cb = iterator = false;
} else if (check(v)) {
cb(null, getResult(true, x));
cb = iterator = false;
}
}
callback();
}.bindenv(this));
}
if (limit == null) {
eachfn(arr, iteratee, done);
} else {
eachfn(arr, limit, iteratee, done);
}
};
}
static function _rest(func) {
return function(...) {
local first, rest;
if (vargv.len() > 0) {
first = vargv[0];
vargv.remove(0);
rest = vargv;
} else {
first = null;
rest = [];
}
return func(first, rest);
}.bindenv(this);
}
static function _range(start, end, step = 1, fromRight = false) {
local index = -1,
length = _nativeMax(math.ceil((end - start) / (step || 1)), 0),
result = array(length);
while (length--) {
result[fromRight ? length : ++index] = start;
start += step;
}
return result;
}
}
The MIT License (MIT)
Copyright (c) 2016 Electric Imp
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
function each() {
function logval(val, done) {
imp.wakeup(val, function() {
server.log(val);
done()
});
}
function logvalsync(val, done) {
server.log(val);
done()
}
server.log("start")
async.each([1, 2, 3], logval, function(err) {
if (err) server.error(err);
else server.log("done");
});
}
function forEachOf() {
function logval(val, key, done) {
imp.wakeup(val, function() {
server.log(key + ": " + val);
done()
});
}
function logvalsync(val, key, done) {
server.log(key + ": " + val);
done()
}
server.log("start")
async.forEachOf({ "one": 1, "two": 2, "three": 3 }, logval, function(err) {
if (err) server.error(err);
else server.log("done");
});
}
function forEachOfSeries() {
function logval(val, key, done) {
imp.wakeup(val, function() {
server.log(key + ": " + val);
done()
});
}
function logvalsync(val, key, done) {
server.log(key + ": " + val);
done()
}
server.log("start")
async.forEachOfSeries({ "one": 1, "two": 2, "three": 3 }, logvalsync, function(err) {
if (err) server.error(err);
else server.log("done - table");
async.forEachOfSeries([ 1, 2, 3 ], logval, function(err) {
if (err) server.error(err);
else server.log("done - array");
});
});
}
function map() {
function square(val, done) {
imp.wakeup(math.rand() % 3, function() {
server.log("square of " + val)
return done(null, val * val);
});
}
server.log("start");
async.map([1, 2, 3], square, function(err, results) {
server.log("done array - " + http.jsonencode(results));
async.map({"one":1, "two":2, "three":3}, square, function(err, results) {
server.log("done table - " + http.jsonencode(results));
})
})
}
function mapSeries() {
function square(val, done) {
imp.wakeup(math.rand() % 3, function() {
server.log("square of " + val)
return done(null, val * val);
});
}
server.log("start");
async.mapSeries([1, 2, 3], square, function(err, results) {
server.log("done array - " + http.jsonencode(results));
async.mapSeries({"one":1, "two":2, "three":3}, square, function(err, results) {
server.log("done table - " + http.jsonencode(results));
})
})
}
function filter() {
function greater_than_one(val, done) {
imp.wakeup(math.rand() % 3, function() {
server.log("greater_than_one of " + val + " = " + (val > 1))
return done(null, val > 1);
});
}
server.log("start");
async.filter([1, 2, 3, 1], greater_than_one, function(err, results) {
server.log("done - " + http.jsonencode(results));
})
}
function filterSeries() {
function greater_than_one(val, done) {
imp.wakeup(math.rand() % 3, function() {
server.log("greater_than_one of " + val + " = " + (val > 1))
return done(null, val > 1);
});
}
server.log("start");
async.filter([1, 2, 3, 1], greater_than_one, function(err, results) {
server.log("done - " + http.jsonencode(results));
})
}
function reject() {
function less_than_two(val, done) {
imp.wakeup(math.rand() % 3, function() {
server.log("less_than_two of " + val + " = " + (val < 2))
return done(null, val < 2);
});
}
server.log("start");
async.reject([0, 1, 2, 3, 1], less_than_two, function(err, results) {
server.log("done - " + http.jsonencode(results));
})
}
function rejectSeries() {
function less_than_two(val, done) {
imp.wakeup(math.rand() % 3, function() {
server.log("less_than_two of " + val + " = " + (val < 2))
return done(null, val < 2);
});
}
server.log("start");
async.rejectSeries([0, 1, 2, 3, 1], less_than_two, function(err, results) {
server.log("done - " + http.jsonencode(results));
})
}
function reduce() {
function add(memo, item, callback) {
callback(null, memo + item);
}
server.log("start");
async.reduce([1, 2, 3], 0, add, function(err, result) {
if (err) server.error(err);
else server.log("done - array = " + result);
async.reduce(["one ", "two ", "three "], "", add, function(err, result) {
if (err) server.error(err);
else server.log("done - table = " + result);
async.reduceRight(["one ", "two ", "three "], "", add, function(err, result) {
if (err) server.error(err);
else server.log("done - reverse = " + result);
});
});
});
}
function detect() {
function len_gt_four(item, callback) {
imp.wakeup(math.rand() % 4, function() {
// server.log(item + ".len() = " + item.len() + " == " + (item.len() > 4));
callback(null, item.len() > 4);
})
}
server.log("start");
async.detect(["one", "four", "seven", "nineteen"], len_gt_four, function(err, result) {
if (err) server.error(err);
else server.log("done - array = " + result);
})
}
function detectSeries() {
function len_gt_four(item, callback) {
imp.wakeup(math.rand() % 4, function() {
server.log(item + ".len() = " + item.len() + " == " + (item.len() > 4));
callback(null, item.len() > 4);
})
}
server.log("start");
async.detectSeries(["one", "four", "seven", "nineteen"], len_gt_four, function(err, result) {
if (err) server.error(err);
else server.log("done - array = " + result);
})
}
function some() {
function len_gt_four(item, callback) {
imp.wakeup(math.rand() % 3, function() {
// server.log(item + ".len() = " + item.len() + " == " + (item.len() > 4));
callback(null, item.len() > 4);
})
}
server.log("start");
async.some({ "1":"one", "4":"four", "9":"nine", "10":"ten"}, len_gt_four, function(err, result) {
if (err) server.error(err);
else server.log("done - table = " + result);
async.some(["one", "four", "seven", "nineteen"], len_gt_four, function(err, result) {
if (err) server.error(err);
else server.log("done - array = " + result);
})
})
}
function every() {
function len_gt_four(item, callback) {
imp.wakeup(math.rand() % 3, function() {
// server.log(item + ".len() = " + item.len() + " == " + (item.len() > 4));
callback(null, item.len() > 4);
})
}
server.log("start");
async.every({ "1":"one", "4":"four", "9":"nine", "10":"ten"}, len_gt_four, function(err, result) {
if (err) server.error(err);
else server.log("done - table = " + result);
async.every(["hundred", "twenty", "seven", "nineteen"], len_gt_four, function(err, result) {
if (err) server.error(err);
else server.log("done - array = " + result);
})
})
}
function concat() {
function rand(item, callback) {
imp.wakeup(math.rand() % 4, function() {
callback(null, [item + ":" + math.rand()]);
})
}
server.log("start");
async.concat(["a", "b", "c", "d"], rand, function(err, result) {
if (err) server.error(err);
else server.log("done - array = " + http.jsonencode(result));
})
}
function concatSeries() {
function rand(item, callback) {
imp.wakeup(math.rand() % 4, function() {
callback(null, [item + ":" + math.rand()]);
})
}
server.log("start");
async.concatSeries(["a", "b", "c", "d"], rand, function(err, result) {
if (err) server.error(err);
else server.log("done - array = " + http.jsonencode(result));
})
}
function sortBy() {
function getfield(item, callback) {
imp.wakeup(math.rand() % 3, function() {
callback(null, item.name);
})
}
server.log("start");
async.sortBy([ {"name":"file_C"}, {"name":"file_A"}, {"name":"file_B"} ], getfield, function(err, results) {
if (err) server.error(err);
else server.log("done - array = " + http.jsonencode(results));
});
}
function series() {
function log(msg) {
return function(callback) {
imp.wakeup(math.rand() % 4, function() {
server.log(msg);
callback(null, msg);
})
}
}
server.log("start");
async.series({ "a1": log("a"), "b2": log("b"), "c3": log("c") }, function(err, results) {
if (err) server.error(err);
else server.log("done - " + http.jsonencode(results));
});
}
function parallel() {
function log(msg) {
return function(callback) {
imp.wakeup(math.rand() % 4, function() {
server.log(msg);
callback(null, msg);
})
}
}
server.log("start");
async.parallel([ log("a"), log("b"), log("c") ], function(err, results) {
if (err) server.error(err);
else server.log("done - " + http.jsonencode(results));
});
}
function whilst() {
server.log("start");
local count = 0;
async.whilst(
function() {
return count < 5;
},
function(callback) {
count++;
imp.wakeup(1, function() {
callback(null, count);
});
},
function(err, n) {
// 5 seconds have passed, n = 5
if (err) server.error(err);
else server.log("done - " + n)
}
);
}
function until() {
server.log("start");
local count = 0;
async.until(
function() {
return count >= 5;
},
function(callback) {
count++;
imp.wakeup(1, function() {
callback(null, count);
});
},
function(err, n) {
// 5 seconds have passed, n = 5
if (err) server.error(err);
else server.log("done - " + n)
}
);
}
function during() {
server.log("start");
local count = 0;
async.during(
function(callback) {
callback(null, count < 5);
},
function(callback) {
count++;
imp.wakeup(1, function() {
callback(null, count);
});
},
function(err) {
// 5 seconds have passed
if (err) server.error(err);
else server.log("done")
}
);
}
function forever() {
function dosomething(callback = null) {
imp.wakeup(1, function() {
server.log("do something");
callback(math.rand() % 10 == 0 ? "done" : null);
});
}
server.log("start")
async.forever(dosomething, function(err) {
server.log("done")
})
}
function waterfall() {
async.waterfall([
function(callback) {
server.log("first")
callback(null, "one", "two");
},
function(arg1, arg2, callback) {
// arg1 now equals 'one' and arg2 now equals 'two'
server.log("second - " + arg1 + ", " + arg2)
callback(null, "three");
},
function(arg1, callback) {
// arg1 now equals 'three'
server.log("third - " + arg1)
callback(null, "done");
}
], function (err, result) {
// result now equals 'done'
if (err) server.error(err);
else server.log("done - " + http.jsonencode(result))
});
}
function seq() {
local doall = async.compose(
function(arg1, callback) {
server.log("first - " + arg1)
callback(null, "one");
},
function(arg1, callback) {
server.log("second - " + arg1)
callback(null, "three");
},
function(arg1, callback) {
// arg1 now equals 'three'
server.log("third - " + arg1)
callback(null, "done");
}
);
doall("zero", function(err, result) {
// result now equals 'done'
if (err) server.error(err);
else server.log("done - " + http.jsonencode(result))
});
}
function applyEach() {
function one(arg1, arg2, done) {
server.log("one = " + arg1 + ", " + arg2)
done();
}
function two(arg1, arg2, callback) {
server.log("two = " + arg1 + ", " + arg2)
done();
}
function three(arg1, arg2, donedone) {
server.log("three = " + arg1 + ", " + arg2)
done();
}
function four(arg1, done) {
server.log("four = " + arg1)
done();
}
function five(arg1, done) {
server.log("five = " + arg1)
done();
}
async.applyEach([one, two, three], "param1", "param2", function(err) {
if (err) server.error(err);
else server.log("done");
async.each(
["paramA", "paramB"],
async.applyEach([four, five]),
function(err) {
// NOTE: So far I can't get this callback to fire
if (err) server.error(err);
else server.log("done")
}.bindenv(this)
);
});
}
function constant() {
function callback(err, arg1, arg2 = null) {
server.log(err + ", " + arg1 + ", " + arg2)
}
async.constant("a", "b")(callback);
}
function asyncify() {
function log(val) {
server.log(val);
if (val == "crash") throw "false"
return true;
}
async.asyncify(log)("hello", function(err, res = null) {
if (err) server.error(err);
else server.log("done - " + res)
async.asyncify(log)("crash", function(err, res = null) {
if (err) server.error(err);
else server.log("done - " + res)
});
})
}
function range() {
local zero = async._range(0, 5);
local one = async._range(3, 10);
local two = async._range(10, 100, 10);
local three = async._range(1, 10, 1, true);
server.log("zero = " + http.jsonencode(zero));
server.log("one = " + http.jsonencode(one));
server.log("two = " + http.jsonencode(two));
server.log("three = " + http.jsonencode(three));
}
function times() {
function log(val, callback) {
server.log("Time: " + (++val));
callback(null, val*val);
}
async.times(5, log, function(err, res = null) {
if (err) server.error(err);
else server.log("done - " + http.jsonencode(res))
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment