Commit 64e85b41 authored by Bastien ROUCARIÈS's avatar Bastien ROUCARIÈS

Add 'module-function-loop/' from commit '4e4499cc'

git-subtree-dir: module-function-loop
git-subtree-mainline: 22776e00
git-subtree-split: 4e4499cc
parents 22776e00 4e4499cc
.nyc_output
node_modules
# function-loop
Run a list of functions in order in a given object context. The
functions can be callback-taking or promise-returning.
This module is
[zalgo-exposing](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony),
meaning that synchronous calls to the cb functions will result in a
sync call to the supplied cb, and async calls will result in the cb
being called asynchronously. It does not artificially defer if
callbacks are called synchronously.
## API
`loop(context, functionList, doneCallback, errorCallback)`
Run all the functions in the context of the `context` object, and then
call the `doneCallback` or call the `errorCallback` if there are any
errors.
module.exports = loop
// this weird little engine is to loop if the cb's keep getting
// called synchronously, since that's faster and makes shallower
// stack traces, but recurse if any of them don't fire this tick
function loop (self, arr, cb, onerr, i) {
if (!i)
i = 0
var running = false
while (i < arr.length && !running) {
running = true
var sync = true
try {
var ret = arr[i].call(self, next)
} catch (er) {
return onerr.call(self,er)
}
if (ret && typeof ret.then === 'function')
ret.then(next.bind(self, null), onerr.bind(self))
i++
sync = false
}
function next (er) {
if (er)
return onerr.call(self, er)
else if (!sync)
return loop(self, arr, cb, onerr, i)
running = false
}
if (i >= arr.length && !running)
return cb.call(self)
}
{
"name": "function-loop",
"version": "1.0.1",
"main": "index.js",
"scripts": {
"test": "tap test.js --100"
},
"repository": {
"type": "git",
"url": "git+https://github.com/isaacs/function-loop.git"
},
"keywords": [],
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
"license": "ISC",
"bugs": {
"url": "https://github.com/isaacs/function-loop/issues"
},
"homepage": "https://github.com/isaacs/function-loop#readme",
"devDependencies": {
"tap": "^9.0.3"
},
"description": "Run a list of functions in order in a given object context. The functions can be callback-taking or promise-returning."
}
var t = require('tap')
var loop = require('./')
var obj = {}
t.test('basic passing operation', function (t) {
var i = 0
loop(obj, [
function (cb) {
t.equal(this, obj, 'this is correct 1')
t.equal(i, 0, '0')
cb()
i++
},
function () {
t.equal(this, obj, 'this is correct 2')
t.equal(i++, 1, '1')
return Promise.resolve(true)
},
function (cb) {
t.equal(this, obj, 'this is correct 3')
t.equal(i++, 2, '2')
setTimeout(cb)
},
function (cb) {
t.equal(this, obj, 'this is correct 4')
t.equal(i++, 3, '3')
process.nextTick(cb)
}
], function () {
t.equal(this, obj, 'this is correct 5')
t.equal(i++, 4, '4')
t.end()
}, function (er) {
throw er
})
t.equal(i, 2, '2, after loop() call')
})
t.test('throws', function (t) {
loop(obj, [
function (cb) {
t.equal(this, obj, 'this is correct')
throw new Error('foo')
},
function () {
t.fail('should not get here')
}
], function () {
t.fail('should not get here')
}, function (er) {
t.match(er, { message: 'foo' })
t.end()
})
})
t.test('all sync', function (t) {
var i = 0
loop(obj, [
function (cb) { t.equal(i++, 0); cb() },
function (cb) { t.equal(i++, 1); cb() },
function (cb) { t.equal(i++, 2); cb() },
function (cb) { t.equal(i++, 3); cb() },
function (cb) { t.equal(i++, 4); cb() }
], function () {
t.equal(i++, 5)
}, function (er) {
throw er
})
t.equal(i, 6)
t.end()
})
t.test('broken promise', function (t) {
loop(obj, [
function (cb) {
t.equal(this, obj, 'this is correct')
return Promise.reject(new Error('foo'))
},
function () {
t.fail('should not get here')
}
], function () {
t.fail('should not get here')
}, function (er) {
t.equal(this, obj, 'this is correct')
t.match(er, { message: 'foo' })
t.end()
})
})
t.test('cb err', function (t) {
loop(obj, [
function (cb) {
t.equal(this, obj, 'this is correct')
cb(new Error('foo'))
},
function () {
t.fail('should not get here')
}
], function () {
t.fail('should not get here')
}, function (er) {
t.equal(this, obj, 'this is correct')
t.match(er, { message: 'foo' })
t.end()
})
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment