Comparing version 2.0.0 to 2.3.0
51
index.js
var util = require('util') | ||
module.exports = ifAsync | ||
var OK = 0 | ||
var THEN = 1 | ||
var EXPECT_THEN = 1 | ||
module.exports = function() { | ||
function ifAsync() { | ||
@@ -18,3 +20,3 @@ var clauses = Array.prototype.slice.call(arguments, 0) | ||
if (clauses.length === 1) { | ||
fluentState = THEN | ||
fluentState = EXPECT_THEN | ||
} else if (clauses.length % 2 === 1) { | ||
@@ -49,2 +51,6 @@ elseClause = clauses.pop() | ||
functor.then = function(fn) { | ||
if (fluentState !== EXPECT_THEN) { | ||
throw new Error('not expecting a then() call now') | ||
} | ||
fluentState = OK | ||
@@ -55,4 +61,29 @@ clauses.push(fn) | ||
functor.and = function(fn) { | ||
var predicate = clauses.shift() | ||
// logical AND using ifAsync | ||
clauses.push( | ||
ifAsync(predicate) | ||
.then(fn) | ||
.else(elseFalse) | ||
) | ||
return functor | ||
} | ||
functor.or = function(fn) { | ||
var predicate = clauses.shift() | ||
// logical OR | ||
clauses.push( | ||
ifAsync(predicate) | ||
.then(elseTrue) | ||
.elseIf(fn) | ||
.then(elseTrue) | ||
.else(elseFalse) | ||
) | ||
return functor | ||
} | ||
functor.else = function(fn) { | ||
if (fluentState === THEN) { | ||
if (fluentState === EXPECT_THEN) { | ||
throw new Error('only then() may be called after elseIf()') | ||
@@ -66,3 +97,3 @@ } | ||
functor.elseif = functor.elseIf = function(fn) { | ||
if (fluentState === THEN) { | ||
if (fluentState === EXPECT_THEN) { | ||
throw new Error('only then() may be called after elseIf()') | ||
@@ -74,3 +105,3 @@ } | ||
// allow only then after a call to elseif | ||
fluentState = THEN | ||
fluentState = EXPECT_THEN | ||
return functor | ||
@@ -84,2 +115,10 @@ } | ||
setImmediate(callback) | ||
} | ||
function elseTrue(callback) { | ||
callback(null, true) | ||
} | ||
function elseFalse(callback) { | ||
callback(null, false) | ||
} |
{ | ||
"name": "if-async", | ||
"version": "2.0.0", | ||
"description": "", | ||
"version": "2.3.0", | ||
"keywords": [ | ||
"async" | ||
], | ||
"description": "", | ||
"main": "index.js", | ||
@@ -24,4 +24,5 @@ "scripts": { | ||
"devDependencies": { | ||
"mocha": "^2.1.0", | ||
"should": "^4.6.1" | ||
} | ||
} |
@@ -1,6 +0,7 @@ | ||
# if-async | ||
async conditional execution for standalone or async.js use | ||
# if-async [![Build Status](https://secure.travis-ci.org/kessler/if-async.png?branch=master)](http://travis-ci.org/kessler/if-async) | ||
### Example 1: Using with Async.js | ||
async conditional execution for async.js or standalone usage | ||
## Example 1: Using with Async.js | ||
```javascript | ||
@@ -12,3 +13,5 @@ var async = require('async') | ||
foo, | ||
ifAsync(predicate1).then(consequent1).else(else1), | ||
ifAsync(predicate1).and(predicate2).then(consequent12) | ||
.elseIf(predicate3).then(consequent3) | ||
.else(else1), | ||
bar | ||
@@ -19,3 +22,6 @@ ]) | ||
function predicate1(callback) { fs.stat(... callback ...) } | ||
function consequent1(callback) { ... } | ||
function predicate2(callback) { fs.stat(... callback ...) } | ||
function consequent12(callback) { ... } | ||
function predicate3(callback) { fs.stat(... callback ...) } | ||
function consequent3(callback) { ... } | ||
function else1(callback) { ... } | ||
@@ -25,3 +31,3 @@ function bar(callback) { ... } | ||
### Example 2: Standalone usage | ||
## Example 2: Standalone usage | ||
@@ -43,10 +49,70 @@ ```javascript | ||
### API Reference | ||
## API Reference | ||
Two main concepts that are used throughout this reference are predicate and consequent. | ||
#### Using fluent interface | ||
#### Predicate | ||
in the context of ifAsync, a predicate is an async function that calls back with an error or a value. That value evaluates to true or false. e.g | ||
```javascript | ||
function predicate(callback) { | ||
if (bar) return callback(null, 1) | ||
else if (foo) return callback() // same as callback(null, false) | ||
else return callback(new Error('fail')) | ||
} | ||
``` | ||
var functor = ifAsync(predicate1).then(consequent1).elseIf(predicate2).then(consequent2).else(defaultConsequent) | ||
#### Consequent | ||
in the context of ifAsync and consequent is an async function that is invoked as a result of an evaluation of a predicate, e.g | ||
```javascript | ||
function consequent(callback) { | ||
callback(null, 'dont care') | ||
} | ||
``` | ||
#### Using function arguments | ||
#### ifAsync(Array|Function) | ||
Call this function with an array of functions or a single function the return value is a new function that will run all the logic and invoke a callback parameter in the end: | ||
var functor = ifAsync(predicate1, consequent1, predicate2, consequent2, defaultConsequent) | ||
```javascript | ||
var functor = ifAsync(f1, f2, f3) | ||
functor(function(err) { | ||
// f1 is evaluated and then f2 or f3 will be called accordingly, then this callback is called | ||
}) | ||
``` | ||
When calling with an array of functions, the array is divided into pairs. The pair's first member is a predicate and the second is a consequent. If the array contains an odd number of functions then the last function is considered the default consequent (else clause) | ||
When calling with a single function, it is considered a predicate and the user is expected to call then() at least once (an error will be thrown otherwise) | ||
Both array style calls and fluent interface can be mixed. e.g ```ifAsync(f1,f2).elseIf(f3).then(f4)``` which is equivalent to ```ifAsync(f1).then(f2).elseIf(f3).then(f4)``` | ||
#### .then(Function) | ||
```javascript | ||
ifAsync(Function f1).then(Function f2) | ||
``` | ||
f1 is a predicate and f2 is a consequent. Each ifAsync must include at least one then consequent | ||
#### .and(Function) | ||
```javascript | ||
ifAsync(Function f1).and(Function f2).then(Function f3) | ||
``` | ||
connect predicates f1 and f2 with a logical AND operator | ||
#### .or(Function) | ||
```javascript | ||
ifAsync(Function f1).or(Function f2).then(Function f3) | ||
``` | ||
connect predicates f1 and f2 with a logical OR operator | ||
#### .elseIf(Function) | ||
```javascript | ||
ifAsync(Function f1).then(Function f2).elseIf(Function f3).then(Function f4) | ||
``` | ||
evaluate the first predicate (f1) if it evalutes to true then run consequent f2 otherwise evaluate f3 and if that is true, run consequent f4 | ||
elseIf() is case insensitive, you can also use elseif() | ||
#### .else(Function) | ||
```javascript | ||
ifAsync(Function f1).then(Function f2).else(Function f3) | ||
``` | ||
The default consequent, it is optional and is executed if f1 predicate above evaluates to false |
171
test.js
@@ -154,3 +154,174 @@ var ifAsync = require('./index.js') | ||
describe('has an and() operator', function () { | ||
it('ifAsync(true).and(false) should invoke both predicates and the else consequent', function (done) { | ||
var p1Invoked = false | ||
var p2Invoked = false | ||
var c1Invoked = false | ||
var c2Invoked = false | ||
ifAsync(function(callback) { | ||
p1Invoked = true | ||
callback(null, true) | ||
}) | ||
.and(function (callback) { | ||
p2Invoked = true | ||
callback(null, false) | ||
}).then(function(cb) { | ||
c1Invoked = true | ||
cb() | ||
}).else(function (cb) { | ||
c2Invoked = true | ||
cb() | ||
})(function (err) { | ||
p1Invoked.should.be.true | ||
p2Invoked.should.be.true | ||
c1Invoked.should.be.false | ||
c2Invoked.should.be.true | ||
done() | ||
}) | ||
}) | ||
it('ifAsync(false).and(*) should invoke the first predicate and the second (else) consequent, it should not invoke the second predicate', function(done) { | ||
var p1Invoked = false | ||
var p2Invoked = false | ||
var c1Invoked = false | ||
var c2Invoked = false | ||
ifAsync(function(callback) { | ||
p1Invoked = true | ||
callback(null, false) | ||
}) | ||
.and(function (callback) { | ||
p2Invoked = true | ||
callback(null, true) | ||
}).then(function(cb) { | ||
c1Invoked = true | ||
cb() | ||
}).else(function (cb) { | ||
c2Invoked = true | ||
cb() | ||
})(function (err) { | ||
p1Invoked.should.be.true | ||
p2Invoked.should.be.false | ||
c1Invoked.should.be.false | ||
c2Invoked.should.be.true | ||
done() | ||
}) | ||
}) | ||
it('ifAsync(true).and(true) should invoke both predicates and the first (then) consequent', function(done) { | ||
var p1Invoked = false | ||
var p2Invoked = false | ||
var c1Invoked = false | ||
var c2Invoked = false | ||
ifAsync(function(callback) { | ||
p1Invoked = true | ||
callback(null, true) | ||
}) | ||
.and(function (callback) { | ||
p2Invoked = true | ||
callback(null, true) | ||
}).then(function(cb) { | ||
c1Invoked = true | ||
cb() | ||
}).else(function (cb) { | ||
c2Invoked = true | ||
cb() | ||
})(function (err) { | ||
p1Invoked.should.be.true | ||
p2Invoked.should.be.true | ||
c1Invoked.should.be.true | ||
c2Invoked.should.be.false | ||
done() | ||
}) | ||
}) | ||
}) | ||
describe('has an or() operator', function () { | ||
it('ifAsync(true).or(*) should invoke the first predicate and the first (then) consequent, it should not invoke the second predicate', function (done) { | ||
var p1Invoked = false | ||
var p2Invoked = false | ||
var c1Invoked = false | ||
var c2Invoked = false | ||
ifAsync(function(callback) { | ||
p1Invoked = true | ||
callback(null, true) | ||
}) | ||
.or(function (callback) { | ||
p2Invoked = true | ||
callback(null, true) | ||
}).then(function(cb) { | ||
c1Invoked = true | ||
cb() | ||
}).else(function (cb) { | ||
c2Invoked = true | ||
cb() | ||
})(function (err) { | ||
p1Invoked.should.be.true | ||
p2Invoked.should.be.false | ||
c1Invoked.should.be.true | ||
c2Invoked.should.be.false | ||
done() | ||
}) | ||
}) | ||
it('ifAsync(false).or(true) should invoke both predicates and the first (then) consequent', function (done) { | ||
var p1Invoked = false | ||
var p2Invoked = false | ||
var c1Invoked = false | ||
var c2Invoked = false | ||
ifAsync(function(callback) { | ||
p1Invoked = true | ||
callback(null, false) | ||
}) | ||
.or(function (callback) { | ||
p2Invoked = true | ||
callback(null, true) | ||
}).then(function(cb) { | ||
c1Invoked = true | ||
cb() | ||
}).else(function (cb) { | ||
c2Invoked = true | ||
cb() | ||
})(function (err) { | ||
p1Invoked.should.be.true | ||
p2Invoked.should.be.true | ||
c1Invoked.should.be.true | ||
c2Invoked.should.be.false | ||
done() | ||
}) | ||
}) | ||
it('ifAsync(false).or(false) should invoke both predicates and the second (else) consequent', function (done) { | ||
var p1Invoked = false | ||
var p2Invoked = false | ||
var c1Invoked = false | ||
var c2Invoked = false | ||
ifAsync(function(callback) { | ||
p1Invoked = true | ||
callback(null, false) | ||
}) | ||
.or(function (callback) { | ||
p2Invoked = true | ||
callback(null, false) | ||
}).then(function(cb) { | ||
c1Invoked = true | ||
cb() | ||
}).else(function (cb) { | ||
c2Invoked = true | ||
cb() | ||
})(function (err) { | ||
p1Invoked.should.be.true | ||
p2Invoked.should.be.true | ||
c1Invoked.should.be.false | ||
c2Invoked.should.be.true | ||
done() | ||
}) | ||
}) | ||
}) | ||
function pTrue (callback) { | ||
@@ -157,0 +328,0 @@ callback(null, true) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
15727
393
115
0
2