synchronous-promise
Advanced tools
Comparing version 1.0.18 to 2.0.0
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
window.SynchronousPromise = require('./index').SynchronousPromise; | ||
},{"./index":2}],2:[function(require,module,exports){ | ||
"use strict"; | ||
function argumentsToArray(args) { | ||
return Array.prototype.slice.apply(args); | ||
} | ||
(function (win) { | ||
"use strict"; | ||
function makeArrayFrom(obj) { | ||
return Array.prototype.slice.apply(obj); | ||
} | ||
function log() { | ||
console.log((new Date()).getTime(), makeArrayFrom(arguments)); | ||
} | ||
var | ||
PENDING = "pending", | ||
RESOLVED = "resolved", | ||
REJECTED = "rejected"; | ||
function looksLikePromise(thing) { | ||
return thing && | ||
thing.then && | ||
typeof (thing.then) === "function" && | ||
typeof (thing.catch) === "function"; | ||
} | ||
function SynchronousPromise(ctorFunction) { | ||
this.status = "pending"; | ||
this._paused = false; | ||
this._next = []; | ||
this._data = []; | ||
this._runConstructorFunction(ctorFunction); | ||
} | ||
SynchronousPromise.prototype = { | ||
then: function (next, fail) { | ||
this._next.push([next, fail]); | ||
if (this._isPendingResolutionOrRejection()) { | ||
return this; | ||
function SynchronousPromise(handler) { | ||
this.status = PENDING; | ||
this._continuations = []; | ||
this._parent = null; | ||
this._paused = false; | ||
if (handler) { | ||
handler.call( | ||
this, | ||
this._continueWith.bind(this), | ||
this._failWith.bind(this) | ||
); | ||
} | ||
} | ||
return this._applyNext(); | ||
}, | ||
catch: function (fn) { | ||
this._next.push([undefined, fn]); | ||
function looksLikeAPromise(obj) { | ||
return obj && typeof (obj.then) === "function"; | ||
} | ||
if (this._isPendingResolutionOrRejection()) { | ||
SynchronousPromise.prototype = { | ||
then: function (nextFn, catchFn) { | ||
var next = SynchronousPromise.unresolved()._setParent(this); | ||
if (this._isRejected()) { | ||
if (this._paused) { | ||
this._continuations.push({ | ||
promise: next, | ||
nextFn: nextFn, | ||
catchFn: catchFn | ||
}); | ||
return next; | ||
} | ||
if (catchFn) { | ||
try { | ||
var catchResult = catchFn(this._error); | ||
if (looksLikeAPromise(catchResult)) { | ||
this._chainPromiseData(catchResult, next); | ||
return next; | ||
} else { | ||
return SynchronousPromise.resolve(catchResult)._setParent(this); | ||
} | ||
} catch (e) { | ||
return SynchronousPromise.reject(e)._setParent(this); | ||
} | ||
} | ||
return SynchronousPromise.reject(this._error)._setParent(this); | ||
} | ||
this._continuations.push({ | ||
promise: next, | ||
nextFn: nextFn, | ||
catchFn: catchFn | ||
}); | ||
this._runResolutions(); | ||
return next; | ||
}, | ||
catch: function (handler) { | ||
if (this._isResolved()) { | ||
return SynchronousPromise.resolve(this._data)._setParent(this); | ||
} | ||
var next = SynchronousPromise.unresolved()._setParent(this); | ||
this._continuations.push({ | ||
promise: next, | ||
catchFn: handler | ||
}); | ||
this._runRejections(); | ||
return next; | ||
}, | ||
pause: function () { | ||
this._paused = true; | ||
return this; | ||
} | ||
return this._applyNext(); | ||
}, | ||
pause: function () { | ||
this._paused = true; | ||
return this; | ||
}, | ||
resume: function () { | ||
this._paused = false; | ||
return this._applyNext(); | ||
}, | ||
_runConstructorFunction: function (ctorFunction) { | ||
var self = this; | ||
this._next.push([ | ||
function (r) { return r; }, | ||
function (err) { throw err; } | ||
]); | ||
var isRun = false; | ||
ctorFunction(function (result) { | ||
if (isRun) { | ||
}, | ||
resume: function () { | ||
var firstPaused = this._findFirstPaused(); | ||
if (firstPaused) { | ||
firstPaused._paused = false; | ||
firstPaused._runResolutions(); | ||
firstPaused._runRejections(); | ||
} | ||
return this; | ||
}, | ||
_setParent: function (parent) { | ||
if (this._parent) { | ||
throw new Error("parent already set"); | ||
} | ||
this._parent = parent; | ||
return this; | ||
}, | ||
_continueWith: function (data) { | ||
var firstPending = this._findFirstPending(); | ||
if (firstPending) { | ||
firstPending._data = data; | ||
firstPending._setResolved(); | ||
} | ||
}, | ||
_findFirstPending: function () { | ||
return this._findFirstAncestor(function (test) { | ||
return test._isPending && test._isPending(); | ||
}); | ||
}, | ||
_findFirstPaused: function () { | ||
return this._findFirstAncestor(function (test) { | ||
return test._paused; | ||
}); | ||
}, | ||
_findFirstAncestor: function (matching) { | ||
var test = this; | ||
var result; | ||
while (test) { | ||
if (matching(test)) { | ||
result = test; | ||
} | ||
test = test._parent; | ||
} | ||
return result; | ||
}, | ||
_failWith: function (error) { | ||
var firstRejected = this._findFirstPending(); | ||
if (firstRejected) { | ||
firstRejected._error = error; | ||
firstRejected._setRejected(); | ||
} | ||
}, | ||
_takeContinuations: function () { | ||
return this._continuations.splice(0, this._continuations.length); | ||
}, | ||
_runRejections: function () { | ||
if (this._paused || !this._isRejected()) { | ||
return; | ||
} | ||
isRun = true; | ||
self._setResolved(); | ||
self._data = [result]; | ||
self._applyNext(); | ||
}, function (err) { | ||
if (isRun) { | ||
var | ||
error = this._error, | ||
continuations = this._takeContinuations(), | ||
self = this; | ||
continuations.forEach(function (cont) { | ||
if (cont.catchFn) { | ||
var catchResult = cont.catchFn(error); | ||
self._handleUserFunctionResult(catchResult, cont.promise); | ||
} else { | ||
cont.promise.reject(error); | ||
} | ||
}); | ||
}, | ||
_runResolutions: function () { | ||
if (this._paused || !this._isResolved()) { | ||
return; | ||
} | ||
var continuations = this._takeContinuations(); | ||
if (looksLikeAPromise(this._data)) { | ||
return this._handleWhenResolvedDataIsPromise(this._data); | ||
} | ||
var data = this._data; | ||
var self = this; | ||
continuations.forEach(function (cont) { | ||
if (cont.nextFn) { | ||
try { | ||
var result = cont.nextFn(data); | ||
self._handleUserFunctionResult(result, cont.promise); | ||
} catch (e) { | ||
self._handleResolutionError(e, cont); | ||
} | ||
} else if (cont.promise) { | ||
cont.promise.resolve(data); | ||
} | ||
}); | ||
}, | ||
_handleResolutionError: function (e, continuation) { | ||
this._setRejected(); | ||
if (continuation.catchFn) { | ||
try { | ||
continuation.catchFn(e); | ||
return; | ||
} catch (e2) { | ||
e = e2; | ||
} | ||
} | ||
if (continuation.promise) { | ||
continuation.promise.reject(e); | ||
} | ||
}, | ||
_handleWhenResolvedDataIsPromise: function (data) { | ||
var self = this; | ||
return data.then(function (result) { | ||
self._data = result; | ||
self._runResolutions(); | ||
}).catch(function (error) { | ||
self._error = error; | ||
self._setRejected(); | ||
self._runRejections(); | ||
}); | ||
}, | ||
_handleUserFunctionResult: function (data, nextSynchronousPromise) { | ||
if (looksLikeAPromise(data)) { | ||
this._chainPromiseData(data, nextSynchronousPromise); | ||
} else { | ||
nextSynchronousPromise.resolve(data); | ||
} | ||
}, | ||
_chainPromiseData: function (promiseData, nextSynchronousPromise) { | ||
promiseData.then(function (newData) { | ||
nextSynchronousPromise.resolve(newData); | ||
}).catch(function (newError) { | ||
nextSynchronousPromise.reject(newError); | ||
}); | ||
}, | ||
_setResolved: function () { | ||
this.status = RESOLVED; | ||
if (!this._paused) { | ||
this._runResolutions(); | ||
} | ||
}, | ||
_setRejected: function () { | ||
this.status = REJECTED; | ||
if (!this._paused) { | ||
this._runRejections(); | ||
} | ||
}, | ||
_isPending: function () { | ||
return this.status === PENDING; | ||
}, | ||
_isResolved: function () { | ||
return this.status === RESOLVED; | ||
}, | ||
_isRejected: function () { | ||
return this.status === REJECTED; | ||
} | ||
}; | ||
isRun = true; | ||
self._setRejected(); | ||
self._data = [err]; | ||
self._applyNext(); | ||
SynchronousPromise.resolve = function (result) { | ||
return new SynchronousPromise(function (resolve, reject) { | ||
if (looksLikeAPromise(result)) { | ||
result.then(function (newResult) { | ||
resolve(newResult); | ||
}).catch(function (error) { | ||
reject(error); | ||
}); | ||
} else { | ||
resolve(result); | ||
} | ||
}); | ||
}, | ||
_setRejected: function () { | ||
this.status = "rejected"; | ||
}, | ||
_setResolved: function () { | ||
this.status = "resolved"; | ||
}, | ||
_setPending: function () { | ||
this.status = "pending"; | ||
}, | ||
_applyNext: function () { | ||
if (this._next.length === 0 || this._paused) { | ||
return this; | ||
} | ||
}; | ||
var next = this._findNext(); | ||
if (!next) { | ||
return this; | ||
} | ||
return this._applyNextHandler(next); | ||
}, | ||
_applyNextHandler: function (handler) { | ||
try { | ||
var data = handler.apply(null, this._data); | ||
SynchronousPromise.reject = function (result) { | ||
return new SynchronousPromise(function (resolve, reject) { | ||
reject(result); | ||
}); | ||
}; | ||
if (looksLikePromise(data)) { | ||
this._handleNestedPromise(data); | ||
return this; | ||
} | ||
SynchronousPromise.unresolved = function () { | ||
return new SynchronousPromise(function (resolve, reject) { | ||
this.resolve = resolve; | ||
this.reject = reject; | ||
}); | ||
}; | ||
this._setResolved(); | ||
this._data = [data]; | ||
return this._applyNext(); | ||
} catch (e) { | ||
this._setRejected(); | ||
this._data = [e]; | ||
return this._applyNext(); | ||
SynchronousPromise.all = function () { | ||
var args = makeArrayFrom(arguments); | ||
if (Array.isArray(args[0])) { | ||
args = args[0]; | ||
} | ||
}, | ||
_findNext: function () { | ||
if (this._isPendingResolutionOrRejection()) { | ||
return undefined; | ||
if (!args.length) { | ||
return SynchronousPromise.resolve([]); | ||
} | ||
var handler = this.status === "resolved" | ||
? this._findFirstResolutionHandler | ||
: this._findFirstRejectionHandler; | ||
return handler ? handler.apply(this) : undefined; | ||
}, | ||
_handleNestedPromise: function (promise) { | ||
this._setPending(); | ||
var self = this; | ||
promise.then(function (d) { | ||
self._setResolved(); | ||
self._data = [d]; | ||
self._applyNext(); | ||
}).catch(function (e) { | ||
self._setRejected(); | ||
self._data = [e]; | ||
self._applyNext(); | ||
return new SynchronousPromise(function (resolve, reject) { | ||
var | ||
allData = [], | ||
numResolved = 0, | ||
doResolve = function () { | ||
if (numResolved === args.length) { | ||
resolve(allData); | ||
} | ||
}, | ||
rejected = false, | ||
doReject = function (err) { | ||
if (rejected) { | ||
return; | ||
} | ||
rejected = true; | ||
reject(err); | ||
}; | ||
args.forEach(function (arg, idx) { | ||
SynchronousPromise.resolve(arg).then(function (thisResult) { | ||
allData[idx] = thisResult; | ||
numResolved += 1; | ||
doResolve(); | ||
}).catch(function (err) { | ||
doReject(err); | ||
}); | ||
}); | ||
}); | ||
}, | ||
_isPendingResolutionOrRejection: function () { | ||
return this.status === "pending"; | ||
}, | ||
_findFirstResolutionHandler: function () { | ||
var next; | ||
while (!next && this._next.length > 0) { | ||
next = this._next.shift()[0]; | ||
} | ||
}; | ||
return next; | ||
}, | ||
_findFirstRejectionHandler: function () { | ||
var next; | ||
while (!next && this._next.length > 0) { | ||
next = this._next.shift()[1]; | ||
} | ||
return next; | ||
if (win) { | ||
window.SynchronousPromise = SynchronousPromise; | ||
} else { | ||
module.exports = { | ||
SynchronousPromise: SynchronousPromise | ||
}; | ||
} | ||
}; | ||
SynchronousPromise.resolve = function (data) { | ||
if (looksLikePromise(data)) { | ||
return data; | ||
} | ||
return new SynchronousPromise(function (resolve) { | ||
resolve(data); | ||
}); | ||
}; | ||
SynchronousPromise.reject = function (error) { | ||
if (looksLikePromise(error)) { | ||
return error; | ||
} | ||
return new SynchronousPromise(function (resolve, reject) { | ||
reject(error); | ||
}); | ||
}; | ||
SynchronousPromise.all = function () { | ||
var args = argumentsToArray(arguments); | ||
if (Array.isArray(args[0])) { | ||
args = args[0]; | ||
} | ||
if (!args.length) { | ||
return SynchronousPromise.resolve([]); | ||
} | ||
return new SynchronousPromise(function (resolve, reject) { | ||
var | ||
allData = [], | ||
numResolved = 0, | ||
doResolve = function () { | ||
if (numResolved === args.length) { | ||
resolve(allData); | ||
} | ||
}, | ||
rejected = false, | ||
doReject = function (err) { | ||
if (rejected) { | ||
return; | ||
} | ||
rejected = true; | ||
reject(err); | ||
}; | ||
args.forEach(function (arg, idx) { | ||
SynchronousPromise.resolve(arg).then(function (thisResult) { | ||
allData[idx] = thisResult; | ||
numResolved += 1; | ||
doResolve(); | ||
}).catch(function (err) { | ||
doReject(err); | ||
}); | ||
}); | ||
}); | ||
}; | ||
SynchronousPromise.unresolved = function () { | ||
var stash = {}; | ||
var result = new SynchronousPromise(function (resolve, reject) { | ||
stash.resolve = resolve; | ||
stash.reject = reject; | ||
}); | ||
result.resolve = stash.resolve; | ||
result.reject = stash.reject; | ||
return result; | ||
}; | ||
module.exports = { | ||
SynchronousPromise: SynchronousPromise | ||
}; | ||
})(typeof (window) === "undefined" ? undefined : window); | ||
},{}]},{},[1]); |
@@ -0,0 +0,0 @@ export interface SynchronousPromise<T> extends Promise<T> { |
497
index.js
@@ -1,225 +0,310 @@ | ||
"use strict"; | ||
function argumentsToArray(args) { | ||
return Array.prototype.slice.apply(args); | ||
} | ||
(function (win) { | ||
"use strict"; | ||
function makeArrayFrom(obj) { | ||
return Array.prototype.slice.apply(obj); | ||
} | ||
function log() { | ||
console.log((new Date()).getTime(), makeArrayFrom(arguments)); | ||
} | ||
var | ||
PENDING = "pending", | ||
RESOLVED = "resolved", | ||
REJECTED = "rejected"; | ||
function looksLikePromise(thing) { | ||
return thing && | ||
thing.then && | ||
typeof (thing.then) === "function" && | ||
typeof (thing.catch) === "function"; | ||
} | ||
function SynchronousPromise(ctorFunction) { | ||
this.status = "pending"; | ||
this._paused = false; | ||
this._next = []; | ||
this._data = []; | ||
this._runConstructorFunction(ctorFunction); | ||
} | ||
SynchronousPromise.prototype = { | ||
then: function (next, fail) { | ||
this._next.push([next, fail]); | ||
if (this._isPendingResolutionOrRejection()) { | ||
return this; | ||
function SynchronousPromise(handler) { | ||
this.status = PENDING; | ||
this._continuations = []; | ||
this._parent = null; | ||
this._paused = false; | ||
if (handler) { | ||
handler.call( | ||
this, | ||
this._continueWith.bind(this), | ||
this._failWith.bind(this) | ||
); | ||
} | ||
} | ||
return this._applyNext(); | ||
}, | ||
catch: function (fn) { | ||
this._next.push([undefined, fn]); | ||
function looksLikeAPromise(obj) { | ||
return obj && typeof (obj.then) === "function"; | ||
} | ||
if (this._isPendingResolutionOrRejection()) { | ||
SynchronousPromise.prototype = { | ||
then: function (nextFn, catchFn) { | ||
var next = SynchronousPromise.unresolved()._setParent(this); | ||
if (this._isRejected()) { | ||
if (this._paused) { | ||
this._continuations.push({ | ||
promise: next, | ||
nextFn: nextFn, | ||
catchFn: catchFn | ||
}); | ||
return next; | ||
} | ||
if (catchFn) { | ||
try { | ||
var catchResult = catchFn(this._error); | ||
if (looksLikeAPromise(catchResult)) { | ||
this._chainPromiseData(catchResult, next); | ||
return next; | ||
} else { | ||
return SynchronousPromise.resolve(catchResult)._setParent(this); | ||
} | ||
} catch (e) { | ||
return SynchronousPromise.reject(e)._setParent(this); | ||
} | ||
} | ||
return SynchronousPromise.reject(this._error)._setParent(this); | ||
} | ||
this._continuations.push({ | ||
promise: next, | ||
nextFn: nextFn, | ||
catchFn: catchFn | ||
}); | ||
this._runResolutions(); | ||
return next; | ||
}, | ||
catch: function (handler) { | ||
if (this._isResolved()) { | ||
return SynchronousPromise.resolve(this._data)._setParent(this); | ||
} | ||
var next = SynchronousPromise.unresolved()._setParent(this); | ||
this._continuations.push({ | ||
promise: next, | ||
catchFn: handler | ||
}); | ||
this._runRejections(); | ||
return next; | ||
}, | ||
pause: function () { | ||
this._paused = true; | ||
return this; | ||
} | ||
return this._applyNext(); | ||
}, | ||
pause: function () { | ||
this._paused = true; | ||
return this; | ||
}, | ||
resume: function () { | ||
this._paused = false; | ||
return this._applyNext(); | ||
}, | ||
_runConstructorFunction: function (ctorFunction) { | ||
var self = this; | ||
this._next.push([ | ||
function (r) { return r; }, | ||
function (err) { throw err; } | ||
]); | ||
var isRun = false; | ||
ctorFunction(function (result) { | ||
if (isRun) { | ||
}, | ||
resume: function () { | ||
var firstPaused = this._findFirstPaused(); | ||
if (firstPaused) { | ||
firstPaused._paused = false; | ||
firstPaused._runResolutions(); | ||
firstPaused._runRejections(); | ||
} | ||
return this; | ||
}, | ||
_setParent: function (parent) { | ||
if (this._parent) { | ||
throw new Error("parent already set"); | ||
} | ||
this._parent = parent; | ||
return this; | ||
}, | ||
_continueWith: function (data) { | ||
var firstPending = this._findFirstPending(); | ||
if (firstPending) { | ||
firstPending._data = data; | ||
firstPending._setResolved(); | ||
} | ||
}, | ||
_findFirstPending: function () { | ||
return this._findFirstAncestor(function (test) { | ||
return test._isPending && test._isPending(); | ||
}); | ||
}, | ||
_findFirstPaused: function () { | ||
return this._findFirstAncestor(function (test) { | ||
return test._paused; | ||
}); | ||
}, | ||
_findFirstAncestor: function (matching) { | ||
var test = this; | ||
var result; | ||
while (test) { | ||
if (matching(test)) { | ||
result = test; | ||
} | ||
test = test._parent; | ||
} | ||
return result; | ||
}, | ||
_failWith: function (error) { | ||
var firstRejected = this._findFirstPending(); | ||
if (firstRejected) { | ||
firstRejected._error = error; | ||
firstRejected._setRejected(); | ||
} | ||
}, | ||
_takeContinuations: function () { | ||
return this._continuations.splice(0, this._continuations.length); | ||
}, | ||
_runRejections: function () { | ||
if (this._paused || !this._isRejected()) { | ||
return; | ||
} | ||
isRun = true; | ||
self._setResolved(); | ||
self._data = [result]; | ||
self._applyNext(); | ||
}, function (err) { | ||
if (isRun) { | ||
var | ||
error = this._error, | ||
continuations = this._takeContinuations(), | ||
self = this; | ||
continuations.forEach(function (cont) { | ||
if (cont.catchFn) { | ||
var catchResult = cont.catchFn(error); | ||
self._handleUserFunctionResult(catchResult, cont.promise); | ||
} else { | ||
cont.promise.reject(error); | ||
} | ||
}); | ||
}, | ||
_runResolutions: function () { | ||
if (this._paused || !this._isResolved()) { | ||
return; | ||
} | ||
var continuations = this._takeContinuations(); | ||
if (looksLikeAPromise(this._data)) { | ||
return this._handleWhenResolvedDataIsPromise(this._data); | ||
} | ||
var data = this._data; | ||
var self = this; | ||
continuations.forEach(function (cont) { | ||
if (cont.nextFn) { | ||
try { | ||
var result = cont.nextFn(data); | ||
self._handleUserFunctionResult(result, cont.promise); | ||
} catch (e) { | ||
self._handleResolutionError(e, cont); | ||
} | ||
} else if (cont.promise) { | ||
cont.promise.resolve(data); | ||
} | ||
}); | ||
}, | ||
_handleResolutionError: function (e, continuation) { | ||
this._setRejected(); | ||
if (continuation.catchFn) { | ||
try { | ||
continuation.catchFn(e); | ||
return; | ||
} catch (e2) { | ||
e = e2; | ||
} | ||
} | ||
if (continuation.promise) { | ||
continuation.promise.reject(e); | ||
} | ||
}, | ||
_handleWhenResolvedDataIsPromise: function (data) { | ||
var self = this; | ||
return data.then(function (result) { | ||
self._data = result; | ||
self._runResolutions(); | ||
}).catch(function (error) { | ||
self._error = error; | ||
self._setRejected(); | ||
self._runRejections(); | ||
}); | ||
}, | ||
_handleUserFunctionResult: function (data, nextSynchronousPromise) { | ||
if (looksLikeAPromise(data)) { | ||
this._chainPromiseData(data, nextSynchronousPromise); | ||
} else { | ||
nextSynchronousPromise.resolve(data); | ||
} | ||
}, | ||
_chainPromiseData: function (promiseData, nextSynchronousPromise) { | ||
promiseData.then(function (newData) { | ||
nextSynchronousPromise.resolve(newData); | ||
}).catch(function (newError) { | ||
nextSynchronousPromise.reject(newError); | ||
}); | ||
}, | ||
_setResolved: function () { | ||
this.status = RESOLVED; | ||
if (!this._paused) { | ||
this._runResolutions(); | ||
} | ||
}, | ||
_setRejected: function () { | ||
this.status = REJECTED; | ||
if (!this._paused) { | ||
this._runRejections(); | ||
} | ||
}, | ||
_isPending: function () { | ||
return this.status === PENDING; | ||
}, | ||
_isResolved: function () { | ||
return this.status === RESOLVED; | ||
}, | ||
_isRejected: function () { | ||
return this.status === REJECTED; | ||
} | ||
}; | ||
isRun = true; | ||
self._setRejected(); | ||
self._data = [err]; | ||
self._applyNext(); | ||
SynchronousPromise.resolve = function (result) { | ||
return new SynchronousPromise(function (resolve, reject) { | ||
if (looksLikeAPromise(result)) { | ||
result.then(function (newResult) { | ||
resolve(newResult); | ||
}).catch(function (error) { | ||
reject(error); | ||
}); | ||
} else { | ||
resolve(result); | ||
} | ||
}); | ||
}, | ||
_setRejected: function () { | ||
this.status = "rejected"; | ||
}, | ||
_setResolved: function () { | ||
this.status = "resolved"; | ||
}, | ||
_setPending: function () { | ||
this.status = "pending"; | ||
}, | ||
_applyNext: function () { | ||
if (this._next.length === 0 || this._paused) { | ||
return this; | ||
} | ||
}; | ||
var next = this._findNext(); | ||
if (!next) { | ||
return this; | ||
} | ||
return this._applyNextHandler(next); | ||
}, | ||
_applyNextHandler: function (handler) { | ||
try { | ||
var data = handler.apply(null, this._data); | ||
SynchronousPromise.reject = function (result) { | ||
return new SynchronousPromise(function (resolve, reject) { | ||
reject(result); | ||
}); | ||
}; | ||
if (looksLikePromise(data)) { | ||
this._handleNestedPromise(data); | ||
return this; | ||
} | ||
SynchronousPromise.unresolved = function () { | ||
return new SynchronousPromise(function (resolve, reject) { | ||
this.resolve = resolve; | ||
this.reject = reject; | ||
}); | ||
}; | ||
this._setResolved(); | ||
this._data = [data]; | ||
return this._applyNext(); | ||
} catch (e) { | ||
this._setRejected(); | ||
this._data = [e]; | ||
return this._applyNext(); | ||
SynchronousPromise.all = function () { | ||
var args = makeArrayFrom(arguments); | ||
if (Array.isArray(args[0])) { | ||
args = args[0]; | ||
} | ||
}, | ||
_findNext: function () { | ||
if (this._isPendingResolutionOrRejection()) { | ||
return undefined; | ||
if (!args.length) { | ||
return SynchronousPromise.resolve([]); | ||
} | ||
var handler = this.status === "resolved" | ||
? this._findFirstResolutionHandler | ||
: this._findFirstRejectionHandler; | ||
return handler ? handler.apply(this) : undefined; | ||
}, | ||
_handleNestedPromise: function (promise) { | ||
this._setPending(); | ||
var self = this; | ||
promise.then(function (d) { | ||
self._setResolved(); | ||
self._data = [d]; | ||
self._applyNext(); | ||
}).catch(function (e) { | ||
self._setRejected(); | ||
self._data = [e]; | ||
self._applyNext(); | ||
return new SynchronousPromise(function (resolve, reject) { | ||
var | ||
allData = [], | ||
numResolved = 0, | ||
doResolve = function () { | ||
if (numResolved === args.length) { | ||
resolve(allData); | ||
} | ||
}, | ||
rejected = false, | ||
doReject = function (err) { | ||
if (rejected) { | ||
return; | ||
} | ||
rejected = true; | ||
reject(err); | ||
}; | ||
args.forEach(function (arg, idx) { | ||
SynchronousPromise.resolve(arg).then(function (thisResult) { | ||
allData[idx] = thisResult; | ||
numResolved += 1; | ||
doResolve(); | ||
}).catch(function (err) { | ||
doReject(err); | ||
}); | ||
}); | ||
}); | ||
}, | ||
_isPendingResolutionOrRejection: function () { | ||
return this.status === "pending"; | ||
}, | ||
_findFirstResolutionHandler: function () { | ||
var next; | ||
while (!next && this._next.length > 0) { | ||
next = this._next.shift()[0]; | ||
} | ||
}; | ||
return next; | ||
}, | ||
_findFirstRejectionHandler: function () { | ||
var next; | ||
while (!next && this._next.length > 0) { | ||
next = this._next.shift()[1]; | ||
} | ||
return next; | ||
if (win) { | ||
window.SynchronousPromise = SynchronousPromise; | ||
} else { | ||
module.exports = { | ||
SynchronousPromise: SynchronousPromise | ||
}; | ||
} | ||
}; | ||
SynchronousPromise.resolve = function (data) { | ||
if (looksLikePromise(data)) { | ||
return data; | ||
} | ||
return new SynchronousPromise(function (resolve) { | ||
resolve(data); | ||
}); | ||
}; | ||
SynchronousPromise.reject = function (error) { | ||
if (looksLikePromise(error)) { | ||
return error; | ||
} | ||
return new SynchronousPromise(function (resolve, reject) { | ||
reject(error); | ||
}); | ||
}; | ||
SynchronousPromise.all = function () { | ||
var args = argumentsToArray(arguments); | ||
if (Array.isArray(args[0])) { | ||
args = args[0]; | ||
} | ||
if (!args.length) { | ||
return SynchronousPromise.resolve([]); | ||
} | ||
return new SynchronousPromise(function (resolve, reject) { | ||
var | ||
allData = [], | ||
numResolved = 0, | ||
doResolve = function () { | ||
if (numResolved === args.length) { | ||
resolve(allData); | ||
} | ||
}, | ||
rejected = false, | ||
doReject = function (err) { | ||
if (rejected) { | ||
return; | ||
} | ||
rejected = true; | ||
reject(err); | ||
}; | ||
args.forEach(function (arg, idx) { | ||
SynchronousPromise.resolve(arg).then(function (thisResult) { | ||
allData[idx] = thisResult; | ||
numResolved += 1; | ||
doResolve(); | ||
}).catch(function (err) { | ||
doReject(err); | ||
}); | ||
}); | ||
}); | ||
}; | ||
SynchronousPromise.unresolved = function () { | ||
var stash = {}; | ||
var result = new SynchronousPromise(function (resolve, reject) { | ||
stash.resolve = resolve; | ||
stash.reject = reject; | ||
}); | ||
result.resolve = stash.resolve; | ||
result.reject = stash.reject; | ||
return result; | ||
}; | ||
module.exports = { | ||
SynchronousPromise: SynchronousPromise | ||
}; | ||
})(typeof (window) === "undefined" ? undefined : window); |
@@ -32,7 +32,7 @@ /* | ||
describe("then", function () { | ||
it("should return the same resolved promise", function () { | ||
it("when resolved, should return a new resolved promise", function () { | ||
var sut = createResolved(); | ||
expect(sut.then(null, function () { })).to.equal(sut); | ||
expect(sut.then(null, function () { })).to.be.instanceOf(SynchronousPromise); | ||
}); | ||
it("should return the same resolved promise v2", function () { | ||
it("should return the new resolved promise v2", function () { | ||
var | ||
@@ -44,15 +44,24 @@ result = createResolved().then(function () { | ||
}); | ||
it("should return the same rejected promise", function () { | ||
it("should return a new rejected promise", function () { | ||
var sut = createRejected(); | ||
expect(sut.then(function () { })).to.equal(sut); | ||
expect(sut.then(function () { })).to.be.instanceOf(SynchronousPromise); | ||
}); | ||
it("should return the same rejected promise v2", function () { | ||
it("should return a new rejected promise v2", function () { | ||
var result = createRejected().then(function () { | ||
/* purposely don't return anything */ | ||
/* purposely don't return anything */ | ||
}); | ||
expect(result).to.be.instanceOf(SynchronousPromise) | ||
}); | ||
it("should call into the catch function when the function given to then throws", function () { | ||
it("should bring the first resolve value into the first then", function () { | ||
var | ||
initial = "123", | ||
captured = null; | ||
createResolved(initial).then(function (data) { | ||
captured = data; | ||
}); | ||
expect(captured).to.equal(initial); | ||
}); | ||
it("should call into the immediate catch function when the function given to then throws", function () { | ||
var | ||
sut = createResolved(), | ||
@@ -63,2 +72,29 @@ expected = "the error", | ||
throw new Error(expected); | ||
}).catch(function (err) { | ||
received = err; | ||
}); | ||
expect(received.message).to.equal(expected); | ||
}); | ||
it("should call the catch from a rejection invoke", () => { | ||
// Arrange | ||
var | ||
expected = "moo", | ||
sut = new SynchronousPromise(function (resolve, reject) { | ||
reject(expected); | ||
}), | ||
captured; | ||
// Act | ||
sut.catch(function (e) { captured = e; }); | ||
// Assert | ||
expect(captured).to.equal(expected); | ||
}); | ||
it("should call into the later catch function when the function given to then throws", function () { | ||
var | ||
sut = createResolved(), | ||
expected = "the error", | ||
received = null; | ||
sut.then(function () { | ||
throw new Error(expected); | ||
}).then(function () { | ||
@@ -70,5 +106,6 @@ return 42; // not a thrower | ||
expect(received).to.eql(new Error(expected)); | ||
expect(received.message).to.equal(expected); | ||
}); | ||
it("should call into following catch rather than the sibling onRejected if onResolved fails", function () { | ||
it("should prefer to call into onRejected over the .catch handler on failure", function () { | ||
var | ||
@@ -84,17 +121,10 @@ sut = createResolved(), | ||
}).catch(function (e) { | ||
console.log(".catch handler"); | ||
catchCaptured = e; | ||
}); | ||
expect(captured).to.be.null; | ||
expect(catchCaptured).to.equal(expected); | ||
expect(captured).to.equal(expected); | ||
expect(catchCaptured).to.be.null; | ||
}); | ||
it("should bring the first resolve value into the first then", function () { | ||
var | ||
initial = "123", | ||
captured = null; | ||
createResolved(initial).then(function (data) { | ||
captured = data; | ||
}); | ||
expect(captured).to.equal(initial); | ||
}); | ||
it("should bring the first rejected value into the first onRejected then handler", function () { | ||
@@ -110,2 +140,3 @@ var | ||
}); | ||
it("should resolve when the first resolution is a resolved promise", function () { | ||
@@ -218,2 +249,17 @@ var | ||
}); | ||
it("should resolve the same value from the same promise multiple times", () => { | ||
// Arrange | ||
var | ||
expected = "multi-pass", | ||
sut = SynchronousPromise.resolve(expected), | ||
captured1, | ||
captured2; | ||
// Act | ||
sut.then(result => captured1 = result); | ||
sut.then(result => captured2 = result); | ||
// Assert | ||
expect(captured1).to.equal(expected); | ||
expect(captured2).to.equal(expected); | ||
}); | ||
}); | ||
@@ -259,3 +305,3 @@ describe("catch", function () { | ||
}); | ||
it("should return a resolved promise if doesn't thrown an error", function () { | ||
it("should return a resolved promise if doesn't throw an error", function () { | ||
var | ||
@@ -290,9 +336,11 @@ promise = createRejected("123"), | ||
capturedError = null; | ||
createRejected(expected).then(function () {}, function (e) { | ||
capturedError = e | ||
}) | ||
.catch(function () { | ||
/* purposely don't return anything */ | ||
capturedError = notExpected; | ||
}) | ||
createRejected(expected).then( | ||
function () { }, | ||
function (e) { | ||
capturedError = e | ||
}) | ||
.catch(function () { | ||
/* purposely don't return anything */ | ||
capturedError = notExpected; | ||
}) | ||
@@ -389,3 +437,3 @@ expect(capturedError).to.equal(expected); | ||
capturedB = e; | ||
}).then(function(data) { | ||
}).then(function (data) { | ||
secondResolve = data; | ||
@@ -409,3 +457,2 @@ }); | ||
}); | ||
}); | ||
@@ -464,3 +511,3 @@ describe("prototype pause", function () { | ||
}); | ||
expect(captured).not.to.be.defined; | ||
expect(captured).to.be.undefined; | ||
promise.resume(); | ||
@@ -478,3 +525,3 @@ expect(captured).to.equal("moo"); | ||
}); | ||
expect(captured).not.to.be.defined; | ||
expect(captured).to.be.undefined; | ||
promise.resume(); | ||
@@ -494,3 +541,3 @@ expect(captured).to.equal(expected); | ||
}); | ||
expect(captured).not.to.be.defined; | ||
expect(captured).to.be.undefined; | ||
promise.resume(); | ||
@@ -715,3 +762,3 @@ expect(captured).to.equal("moon"); | ||
describe("result", function () { | ||
it("should not be resolve or rejected", function () { | ||
it("should not be resolved or rejected", function () { | ||
// Arrange | ||
@@ -730,3 +777,3 @@ var resolved = false, | ||
}); | ||
describe("resolve property", function () { | ||
describe("resolve", function () { | ||
it("should be a function", function () { | ||
@@ -752,2 +799,3 @@ // Arrange | ||
// Act | ||
debugger; | ||
sut.resolve(expected); | ||
@@ -754,0 +802,0 @@ // Assert |
{ | ||
"name": "synchronous-promise", | ||
"version": "1.0.18", | ||
"version": "2.0.0", | ||
"description": "Synchronous Promise-like prototype to use in testing where you would have used an ES6 Promise", | ||
@@ -15,3 +15,5 @@ "main": "index.js", | ||
"autolint": "nodemon -q -x \"run-s -s lint\"", | ||
"lint": "jslint index.js", | ||
"prelint": "node -e \"console.log('Linting started: ', new Date());\"", | ||
"lint": "jshint index.js", | ||
"postlint": "node -e \"console.log('Linting completed: ', new Date());\"", | ||
"pretest": "run-s lint", | ||
@@ -21,3 +23,4 @@ "test": "mocha index.spec.js", | ||
"dist": "browserify browser.js -o dist/synchronous-promise.js", | ||
"prepublish": "run-s -s test dist" | ||
"prepublish": "run-s -s test dist", | ||
"debug": "mocha -w *.spec.js --reporter mocha-yar --debug-brk --inspect" | ||
}, | ||
@@ -27,12 +30,12 @@ "author": "Davyd McColl <davydm@gmail.com> (https://github.com/fluffynuts)", | ||
"devDependencies": { | ||
"browserify": "^14.1.0", | ||
"chai": "^3.5.0", | ||
"jslint": "^0.10.1", | ||
"browserify": "^14.5.0", | ||
"chai": "^4.1.2", | ||
"jshint": "^2.9.5", | ||
"mkdirp": "^0.5.1", | ||
"mocha": "^2.5.3", | ||
"mocha-yar": "^1.0.10", | ||
"nodemon": "^1.10.2", | ||
"npm-run-all": "^2.3.0", | ||
"run-sequence": "^1.2.2" | ||
"mocha": "^4.0.1", | ||
"mocha-yar": "^1.0.12", | ||
"nodemon": "^1.12.1", | ||
"npm-run-all": "^4.1.2", | ||
"run-sequence": "^2.2.0" | ||
} | ||
} |
@@ -0,0 +0,0 @@ # synchronous-promise |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
56767
1453