+1
-1
| { | ||
| "name": "lazy-ass", | ||
| "main": "index.js", | ||
| "version": "0.2.0", | ||
| "version": "0.4.0", | ||
| "homepage": "https://github.com/bahmutov/lazy-ass", | ||
@@ -6,0 +6,0 @@ "license": "MIT", |
+24
-6
@@ -17,2 +17,5 @@ (function initLazyAss() { | ||
| } | ||
| if (arg instanceof Error) { | ||
| return total + arg.name + ' ' + arg.message; | ||
| } | ||
| return total + JSON.stringify(arg, null, 2); | ||
@@ -23,14 +26,29 @@ }, ''); | ||
| var lazyAss = function lazyAss(condition) { | ||
| function lazyAssLogic(condition) { | ||
| var fn = typeof condition === 'function' ? condition : null; | ||
| if (fn) { | ||
| condition = fn(); | ||
| } | ||
| if (!condition) { | ||
| var args = [].slice.call(arguments, 1); | ||
| throw new Error(formMessage(args)); | ||
| if (fn) { | ||
| args.unshift(fn.toString()); | ||
| } | ||
| return new Error(formMessage(args)); | ||
| } | ||
| } | ||
| var lazyAss = function lazyAss() { | ||
| var err = lazyAssLogic.apply(null, arguments); | ||
| if (err) { | ||
| throw err; | ||
| } | ||
| }; | ||
| var lazyAssync = function lazyAssync(condition) { | ||
| if (!condition) { | ||
| var args = [].slice.call(arguments, 1); | ||
| var lazyAssync = function lazyAssync() { | ||
| var err = lazyAssLogic.apply(null, arguments); | ||
| if (err) { | ||
| setTimeout(function () { | ||
| throw new Error(formMessage(args)); | ||
| throw err; | ||
| }, 0); | ||
@@ -37,0 +55,0 @@ } |
+1
-1
| { | ||
| "name": "lazy-ass", | ||
| "description": "Lazy assertions without performance penalty", | ||
| "version": "0.2.0", | ||
| "version": "0.4.0", | ||
| "author": "Gleb Bahmutov <gleb.bahmutov@gmail.com>", | ||
@@ -6,0 +6,0 @@ "bugs": { |
+55
-0
@@ -29,2 +29,15 @@ # lazy-ass | ||
| Concatenates strings, stringifies objects, calls functions - only if | ||
| condition is false. | ||
| ```js | ||
| function environment() { | ||
| // returns string | ||
| } | ||
| var user = {} // an object | ||
| lazyAsync(condition, 'something went wrong for', user, 'in', environment); | ||
| // throws an error with message equivalent of | ||
| // 'something went wrong for ' + JSON.stringify(user) + ' in ' + environment() | ||
| ``` | ||
| ## Why? | ||
@@ -86,2 +99,44 @@ | ||
| ## Predicate function as a condition | ||
| Typically, JavaScript evaluates the condition expression first, then calls *lazyAss*. | ||
| This means the function itself sees only the true / false result, and not the expression | ||
| itself. This makes makes the error messages cryptic | ||
| lazyAss(2 + 2 === 5); | ||
| // Error | ||
| We usually get around this by giving at least one additional message argument to | ||
| explain the condition tested | ||
| lazyAss(2 + 2 === 5, 'addition') | ||
| // Error: addition | ||
| *lazyAss* has a better solution: if you give a function that evaluates the condition | ||
| expression, if the function returns false, the error message will include the source | ||
| of the function, making the extra arguments unnecessary | ||
| lazyAss(function () { return 2 + 2 === 5; }); | ||
| // Error: function () { return 2 + 2 === 5; } | ||
| The condition function has access to any variables in the scope, making it extremely | ||
| powerful | ||
| var foo = 2, bar = 2; | ||
| lazyAss(function () { return foo + bar === 5; }); | ||
| // Error: function () { return foo + bar === 5; } | ||
| In practical terms, I recommend using separate predicates function and | ||
| passing relevant values to the *lazyAss* function. Remember, there is no performance | ||
| penalty! | ||
| var foo = 2, bar = 2; | ||
| function isValidPair() { | ||
| return foo + bar === 5; | ||
| } | ||
| lazyAss(isValidPair, 'foo', foo, 'bar', bar); | ||
| // Error: function isValidPair() { | ||
| // return foo + bar === 5; | ||
| // } foo 2 bar 2 | ||
| ### Small print | ||
@@ -88,0 +143,0 @@ |
@@ -80,3 +80,67 @@ /* global lazyAss */ | ||
| }); | ||
| it('takes error name and message', function () { | ||
| expect(function () { | ||
| lazyAss(false, new Error('hi there')); | ||
| }).to.throwException(function (err) { | ||
| expect(err.message).to.contain('Error'); | ||
| expect(err.message).to.contain('hi there'); | ||
| }); | ||
| }); | ||
| }); | ||
| describe('function as condition', function () { | ||
| it('evaluates the function', function () { | ||
| var called; | ||
| function condition() { called = true; return true; } | ||
| lazyAss(condition); | ||
| expect(called).to.be(true); | ||
| }); | ||
| it('no result is failure', function () { | ||
| function noreturn() {} | ||
| expect(function () { | ||
| lazyAss(noreturn); | ||
| }).to.throwError(); | ||
| }); | ||
| it('adds condition function source to message', function () { | ||
| function myCondition() {} | ||
| expect(function () { | ||
| lazyAss(myCondition); | ||
| }).to.throwException(/myCondition/); | ||
| }); | ||
| it('allows anonymous functions', function () { | ||
| var called; | ||
| lazyAss(function() { return true; }); | ||
| lazyAss(function() { return true; }, 'everything is ok'); | ||
| lazyAss(function() { called = true; return true; }, 'everything is ok'); | ||
| expect(called).to.be(true); | ||
| expect(function () { | ||
| lazyAss(function () {}); | ||
| }).to.throwError(); | ||
| }); | ||
| it('has access via closure', function () { | ||
| var foo = 2, bar = 3; | ||
| expect(function () { | ||
| lazyAss(function () { return foo + bar === 6; }, 'addition'); | ||
| }).to.throwException(function (err) { | ||
| expect(err.message).to.contain('foo + bar'); | ||
| expect(err.message).to.contain('addition'); | ||
| }); | ||
| }); | ||
| it('example', function () { | ||
| var foo = 2, bar = 2; | ||
| function isValidPair() { | ||
| return foo + bar === 4; | ||
| } | ||
| lazyAss(isValidPair, 'foo', foo, 'bar', bar); | ||
| }); | ||
| }); | ||
| }); |
21870
22.35%367
23.57%190
40.74%