Skip to content

Instantly share code, notes, and snippets.

@JeffRMoore
Created March 15, 2017 19:23
Show Gist options
  • Save JeffRMoore/e921845d397f14feb76c937f8aa9c2fd to your computer and use it in GitHub Desktop.
Save JeffRMoore/e921845d397f14feb76c937f8aa9c2fd to your computer and use it in GitHub Desktop.
Experimental version of compose
function compose (middleware) {
if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')
for (const fn of middleware) {
if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
}
return function (context, next, skipNext) {
if (next !== undefined && typeof next !== 'function') {
throw new TypeError('Next must be a function when specified')
}
if (skipNext !== undefined && typeof skipNext !== 'function') {
throw new TypeError('skipNext must be a function when specified')
}
let maxDispatched = -1;
let hasTerminated = false;
let dispatchTo = -1;
return dispatchNext()
function dispatchSkipNext() {
if (hasTerminated) {
throw new Error('middleware called skipNext() more than once');
}
hasTerminated = true;
if (skipNext) {
return skipNext()
}
return Promise.resolve()
}
function checkResolvedValue(value) {
if (!hasTerminated) {
throw new Error('middleware has not called next() or skipNext()');
}
return value;
}
function dispatchNext() {
if (hasTerminated) {
throw new Error('middleware chain has terminated more than once');
}
dispatchTo++;
if (dispatchTo <= maxDispatched) {
throw new Error('middleware called next() more than once');
}
maxDispatched = dispatchTo;
try {
let result;
if (dispatchTo < middleware.length) {
result = middleware[dispatchTo](context, dispatchNext, dispatchSkipNext);
} else {
const terminate = next || dispatchSkipNext
result = terminate();
hasTerminated = true;
}
if (typeof result === 'object' && result !== null && typeof result.then === 'function') {
return result.then(checkResolvedValue);
}
return Promise.reject(new TypeError('Middleware must return a Promise'));
} catch (err) {
return Promise.reject(err);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment