Comparing version 2.0.0 to 3.0.0
331
lib/index.js
@@ -1,43 +0,113 @@ | ||
(function(root) { | ||
"use strict"; | ||
'use strict'; | ||
var PENDING = 0, | ||
FULFILLED = 1, | ||
REJECTED = 2, | ||
FIDELITY = { | ||
promise: promise, | ||
deferred: deferred | ||
}; | ||
const | ||
PENDING = 0, | ||
FULFILLED = 1, | ||
REJECTED = 2, | ||
TRUE = factory(FULFILLED, true), | ||
FALSE = factory(FULFILLED, false), | ||
NULL = factory(FULFILLED, null), | ||
UNDEFINED = factory(undefined), | ||
ZERO = factory(FULFILLED, 0), | ||
EMPTYSTRING = factory(FULFILLED, ''), | ||
function promise(fn) { | ||
/** | ||
* @module fidelity | ||
*/ | ||
FIDELITY = { | ||
promise: promise, | ||
deferred: deferred, | ||
resolve: resolveValue, | ||
PENDING: PENDING, | ||
FULFILLED: FULFILLED, | ||
REJECTED: REJECTED | ||
}; | ||
module.exports = FIDELITY; | ||
var p = { | ||
state: PENDING, | ||
identify: 'fidelity', | ||
value: null, | ||
queue: [], | ||
handlers: { | ||
fulfill: null, | ||
reject: null | ||
/** | ||
* Creates a promise that will be resolved or rejected at some time | ||
* in the future. | ||
* @param {function} fn The function that will do the work of this promise. | ||
* The function is passed two function arguments, `resolve()` and `reject()`. | ||
* Call one of these when the work has completed (or failed). | ||
* @returns {object} A promise object | ||
* @instance | ||
*/ | ||
function promise (fn) { | ||
const p = factory(PENDING, null); | ||
if (typeof fn === 'function') { | ||
fn( | ||
(v) => { | ||
resolve(p, v); | ||
}, | ||
(r) => { | ||
transition(p, REJECTED, r); | ||
} | ||
}; | ||
p.then = then(p); | ||
); | ||
} | ||
return p; | ||
} | ||
if (isA('function', fn)) { | ||
fn( | ||
function(v) { resolve(p, v); }, | ||
function(r) { reject(p, r); } | ||
); | ||
} | ||
/** | ||
* Returns a promise that is resolved with `value`. | ||
* @param {any} value The value to resolve the returned promise with | ||
* @returns {object} A promise resolved with `value` | ||
* @instance | ||
*/ | ||
function resolveValue (value) { | ||
if (value._fidelity) return value; | ||
return p; | ||
switch (value) { | ||
case null: return NULL; | ||
case undefined: return UNDEFINED; | ||
case true: return TRUE; | ||
case false: return FALSE; | ||
case 0: return ZERO; | ||
} | ||
function then(p) { | ||
return function(onFulfilled, onRejected) { | ||
var q = promise(); | ||
if (isA('function', onFulfilled)) { | ||
return factory(FULFILLED, value); | ||
} | ||
/** | ||
* Creates a `deferred` object, containing a promise which may | ||
* be resolved or rejected at some point in the future. | ||
* @returns {object} deferred The deferred object | ||
* @returns {function} deferred.resolve(value) The resolve function | ||
* @returns {function} deferred.reject(cause) The reject function | ||
* @returns {object} deferred.promise The inner promise object | ||
* @instance | ||
*/ | ||
function deferred () { | ||
var resolver, rejecter, | ||
p = promise((resolve, reject) => { | ||
resolver = resolve; | ||
rejecter = reject; | ||
}); | ||
function resolve (value) { | ||
resolver(value); | ||
} | ||
function reject (cause) { | ||
rejecter(cause); | ||
} | ||
return { | ||
promise: p, | ||
resolve: resolve, | ||
reject: reject | ||
}; | ||
} | ||
function factory (state, value) { | ||
const p = { | ||
state: state, | ||
value: value, | ||
then: (onFulfilled, onRejected) => { | ||
const q = factory(PENDING, null); | ||
if (typeof onFulfilled === 'function') { | ||
q.handlers.fulfill = onFulfilled; | ||
} | ||
if (isA('function', onRejected)) { | ||
if (typeof onRejected === 'function') { | ||
q.handlers.reject = onRejected; | ||
@@ -48,128 +118,95 @@ } | ||
return q; | ||
}; | ||
} | ||
}, | ||
queue: [], | ||
handlers: { | ||
get: { | ||
fulfill: null, | ||
reject: null | ||
}, | ||
enumerable: false, | ||
configurable: false | ||
}, | ||
_fidelity: true | ||
}; | ||
return p; | ||
} | ||
function resolve(p, x) { | ||
if (x === p) | ||
reject(p, new TypeError('The promise and its value are the same.')); | ||
function resolve (p, x) { | ||
if (x === p) | ||
transition(p, REJECTED, new TypeError('The promise and its value are the same.')); | ||
if (isPromise(x)) { | ||
if (x.state === PENDING) { | ||
x.then(function(value) { | ||
resolve(p, value); | ||
}, function(cause) { | ||
reject(p, cause); | ||
if (x && x._fidelity) { | ||
if (x.state === PENDING) { | ||
x.then((value) => { | ||
resolve(p, value); | ||
}, (cause) => { | ||
transition(p, REJECTED, cause); | ||
}); | ||
} else { | ||
transition(p, x.state, x.value); | ||
} | ||
} else if (x && ((typeof x === 'function') || (typeof x === 'object'))) { | ||
let called = false, thenFunction; | ||
try { | ||
thenFunction = x.then; | ||
if (thenFunction && (typeof thenFunction === 'function')) { | ||
thenFunction.call(x, (y) => { | ||
if (!called) { | ||
resolve(p, y); | ||
called = true; | ||
} | ||
}, (r) => { | ||
if (!called) { | ||
transition(p, REJECTED, r); | ||
called = true; | ||
} | ||
}); | ||
} else { | ||
transition(p, x.state, x.value); | ||
transition(p, FULFILLED, x); | ||
called = true; | ||
} | ||
} else if (isA('function', x) || isA('object', x)) { | ||
var called = false, thenFunction; | ||
try { | ||
thenFunction = x.then; | ||
if (isA('function', thenFunction)) { | ||
thenFunction.call(x, function(y) { | ||
if (!called) { | ||
resolve(p, y); | ||
called = true; | ||
} | ||
}, function (r) { | ||
if (!called) { | ||
reject(p, r); | ||
called = true; | ||
} | ||
}); | ||
} else { | ||
fulfill(p, x); | ||
called = true; | ||
} | ||
} catch (e) { | ||
if (!called) { | ||
reject(p, e); | ||
called = true; | ||
} | ||
} catch (e) { | ||
if (!called) { | ||
transition(p, REJECTED, e); | ||
called = true; | ||
} | ||
} | ||
else fulfill(p, x); | ||
} | ||
else transition(p, FULFILLED, x); | ||
} | ||
function fulfill(p, result) { | ||
transition(p, FULFILLED, result); | ||
} | ||
function reject(p, cause) { | ||
transition(p, REJECTED, cause); | ||
} | ||
function defaultFulfill(v) { return v; } | ||
function defaultReject(r) { throw r; } | ||
function process(p) { | ||
if (p.state === PENDING) return; | ||
setTimeout(function() { | ||
while(p.queue.length) { | ||
var qp = p.queue.shift(), | ||
handler, value; | ||
if (p.state === FULFILLED) { | ||
handler = qp.handlers.fulfill || defaultFulfill; | ||
} else if (p.state === REJECTED) { | ||
handler = qp.handlers.reject || defaultReject; | ||
} | ||
try { | ||
value = handler(p.value); | ||
} catch(e) { | ||
transition(qp, REJECTED, e); | ||
continue; | ||
} | ||
resolve(qp, value); | ||
function process (p) { | ||
if (p.state === PENDING) return; | ||
setImmediate(() => { | ||
let qp, handler, value; | ||
while(p.queue.length) { | ||
qp = p.queue.shift(); | ||
if (p.state === FULFILLED) { | ||
handler = qp.handlers.fulfill || ((v) => { | ||
return v; | ||
}); | ||
} else if (p.state === REJECTED) { | ||
handler = qp.handlers.reject || ((r) => { | ||
throw r; | ||
}); | ||
} | ||
}, 0); | ||
} | ||
function transition(p, state, value) { | ||
if (p.state === state || | ||
p.state !== PENDING || | ||
arguments.length !== 3) return; | ||
p.state = state; | ||
p.value = value; | ||
process(p); | ||
} | ||
function isA(type, x) { | ||
return x && typeof x === type; | ||
} | ||
function isPromise(x) { | ||
return x && x.identify === 'fidelity'; | ||
} | ||
promise.PENDING = PENDING; | ||
promise.FULFILLED = FULFILLED; | ||
promise.REJECTED = REJECTED; | ||
function deferred() { | ||
var resolver, rejecter, | ||
p = promise(function(resolve, reject) { | ||
resolver = resolve; | ||
rejecter = reject; | ||
}); | ||
function resolve(value) { | ||
resolver(value); | ||
try { | ||
value = handler(p.value); | ||
} catch(e) { | ||
transition(qp, REJECTED, e); | ||
continue; | ||
} | ||
resolve(qp, value); | ||
} | ||
}); | ||
} | ||
function reject(cause) { | ||
rejecter(cause); | ||
} | ||
return { | ||
promise: p, | ||
resolve: resolve, | ||
reject: reject | ||
}; | ||
} | ||
if (module && module.exports) module.exports = FIDELITY; | ||
else root.FIDELITY = FIDELITY; | ||
})(this); | ||
function transition (p, state, value) { | ||
if (p.state === state || | ||
p.state !== PENDING || | ||
arguments.length !== 3) return; | ||
p.state = state; | ||
p.value = value; | ||
process(p); | ||
return p; | ||
} |
{ | ||
"name": "fidelity", | ||
"version": "2.0.0", | ||
"description": "A simple A+ promises implementation", | ||
"main": "lib/index.js", | ||
"directories": { | ||
"test": "test" | ||
}, | ||
"implements": [ | ||
], | ||
"scripts": { | ||
"test": "node_modules/mocha/bin/mocha" | ||
}, | ||
"keywords": [ | ||
"promises", | ||
"promise", | ||
"deferred", | ||
"future", | ||
"aplus", | ||
"A+" | ||
], | ||
"author": "Lance Ball <lanceball@gmail.com> (http://lanceball.com)", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"mocha": "^2.3.3", | ||
"promises-aplus-tests": "^2.1.1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/lance/fidelity" | ||
} | ||
"name": "fidelity", | ||
"version": "3.0.0", | ||
"description": "A simple A+ promises implementation", | ||
"main": "lib/index.js", | ||
"directories": { | ||
"test": "test" | ||
}, | ||
"implements": [], | ||
"scripts": { | ||
"lint": "jshint lib/*.js test/*.js", | ||
"test": "node test/tape-test.js | tap-spec && promises-aplus-tests test/spec-adapter.js", | ||
"coverage": "istanbul cover tape -- test/tape-test.js | tap-spec", | ||
"docs": "jsdoc --verbose -d docs -t ./node_modules/ink-docstrap/template -R README.md lib/index.js", | ||
"prepublish": "nsp check", | ||
"benchmark": "node benchmark/benchmark.js", | ||
"profile": "NODE_ENV=production node --prof test/tape-test.js && FILE=`ls -tr | tail -1` && node --prof-process $FILE | tee processed.txt && rm $FILE" | ||
}, | ||
"keywords": [ | ||
"promises", | ||
"promise", | ||
"deferred", | ||
"future", | ||
"aplus", | ||
"A+" | ||
], | ||
"author": "Lance Ball <lanceball@gmail.com> (http://lanceball.com)", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"bench": "^0.3.6", | ||
"bluebird": "^3.3.5", | ||
"ink-docstrap": "^1.1.4", | ||
"istanbul": "^0.4.3", | ||
"jsdoc": "^3.4.0", | ||
"jshint": "^2.9.2", | ||
"nsp": "^2.4.0", | ||
"promise": "^7.1.1", | ||
"promises-aplus-tests": "^2.1.1", | ||
"q": "^1.4.1", | ||
"tap-spec": "^4.1.1", | ||
"tape": "^4.5.1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/lance/fidelity" | ||
} | ||
} |
# Fidelity | ||
A simple promises-aplus implementation. I wrote this over the course of a few | ||
days with some simple goals in mind. | ||
A simple promises-aplus implementation. Faster than `Q`, slower than `Bluebird`. | ||
Simpler and smaller than both. | ||
- Gain a better understanding of how Promises work | ||
- Pass all of the tests in the [Promises/A+ Compliance Test Suite](https://github.com/promises-aplus/promises-tests) | ||
- Experiment with some of Douglas Crockford's object creation ideas | ||
* eliminate use of the `this` keyword | ||
* eliminate use of the `new` keyword | ||
## Installing | ||
@@ -16,2 +10,6 @@ | ||
## API Documentation | ||
The API is pretty simple, and it's lightly documented [here](http://lanceball.com/fidelity/). | ||
## Usage | ||
@@ -23,22 +21,25 @@ | ||
var promise = require('promise'); | ||
var Fidelity = require('fidelity'); | ||
var p = promise(function(resolve, reject) { | ||
var result = f(); | ||
if (result) { | ||
resolve(f); | ||
} else { | ||
reject('Some error occurred'); | ||
} | ||
}) | ||
Fidelity.promise( (resolve, reject) => { | ||
someAsyncFunction((result, err) => { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve(result); | ||
} | ||
}); | ||
}).then( (val) => { | ||
// Do something with the result. | ||
}); | ||
The object returned from a call to `promise()` has a function, `then()`. This | ||
function takes two arguments, each a function. The first is called with the return | ||
The promise object returned from `promise()` has a function, `then()`. This | ||
takes two function arguments. The first is called with the return | ||
value (if any) of the promise function if it is successfully fulfilled. The | ||
second function is called in the event of an error. | ||
p.then(function(result) { | ||
p.then( (result) => { | ||
console.log('sucessful result ', result); | ||
}, function(err) { | ||
console.log('whoops!', err); | ||
}, (err) => { | ||
console.error('whoops!', err); | ||
}); | ||
@@ -48,2 +49,4 @@ | ||
To run the full suite of the Promises/A+ spec, run `npm test` from the command line. | ||
This module passes all of the tests in the | ||
[Promises/A+ Compliance Test Suite](https://github.com/promises-aplus/promises-tests). | ||
To run the full suite of the Promises/A+ spec, just `npm test` from the command line. |
Sorry, the diff of this file is not supported yet
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
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
14480
12
357
50
12
1