Skip to content

Instantly share code, notes, and snippets.

@strandel
Last active December 14, 2015 12:18
Show Gist options
  • Save strandel/5085045 to your computer and use it in GitHub Desktop.
Save strandel/5085045 to your computer and use it in GitHub Desktop.
Asynchronous chain
function chain() {
var queue = []
, withoutContext = null
function chainer(func) {
queue.push(func)
return chainer
}
chainer.run = function () {return run(queue)}
function run(queue /*, ...*/) {
if (queue.length === 0) return
var skipFirst = 1
, params = slice(arguments, skipFirst)
, restOfQueue = slice(queue, skipFirst)
, func = queue[0]
if (isAsync(func, params)) {
func.apply(withoutContext, params.concat([doneCallback(restOfQueue)]))
} else {
var ret = func.apply(withoutContext, params)
run(restOfQueue, ret)
}
}
function isAsync(func, params) {return func.length > params.length}
function slice(x, skipFromBeginning) {return [].slice.call(x, skipFromBeginning)}
function doneCallback(queue) {return function (/*...*/) {run.apply(withoutContext, [queue].concat(slice(arguments)))}}
return chainer
}
// Example
chain()
(just([1,2,3,4,5,6]))
(filter(even))
(map(double))
(delayTwoSeconds)
(print)
.run()
// Details
function filter(func) {return function (arr) {return arr.filter(func)}}
function map(func) {return function (arr) {return arr.map(func)}}
function just(x) {return function () {return x}}
function even(x) {return x%2==0}
function double(x) {return x*2}
function print(x) {console.log(x)}
function delayTwoSeconds(arr, done) {setTimeout(function () {done(arr)}, 2000)}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment