Skip to content

Instantly share code, notes, and snippets.

@eser
Last active July 1, 2016 12:48
Show Gist options
  • Save eser/3944ba9ccf99810492acb01d5f21ade2 to your computer and use it in GitHub Desktop.
Save eser/3944ba9ccf99810492acb01d5f21ade2 to your computer and use it in GitHub Desktop.
class MiddlewareProxyHandler {
constructor() {
this.middlewares = [];
// this.ignoredKeys = [ 'meta' ];
}
addMiddleware(obj) {
this.middlewares.push(obj);
}
get(target, propertyKey, receiver) {
// if (this.ignoredKeys.indexOf(propertyKey) > -1) {
// return target[propertyKey];
// }
let callStack = [],
callStackIndex = 0,
result = undefined;
for (let middleware of this.middlewares) {
if (middleware[propertyKey] !== undefined) {
if (middleware[propertyKey] !== null && middleware[propertyKey].constructor === Function) {
if (callStack.length === 0) {
(function (resultParameter) {
callStack.push({ scope: undefined, callback: (next) => next(resultParameter) });
})(result);
}
callStack.push({ scope: middleware, callback: middleware[propertyKey] });
}
else {
callStack = [];
result = middleware[propertyKey];
}
}
}
if (callStack.length === 0) {
target[propertyKey] = result;
return target[propertyKey];
}
const next = function () {
const current = callStack[callStackIndex++];
if (current === undefined) {
return arguments[0];
}
const parameters = Array.prototype.slice.call(arguments, 0);
parameters.push(next);
return current.callback.apply(current.scope, parameters);
};
target[propertyKey] = next;
return target[propertyKey];
}
}
function consultant(obj) {
const handler = new MiddlewareProxyHandler(),
instance = new Proxy(obj, handler);
return {
meta: handler,
instance: instance
};
}
const c = consultant({});
c.meta.addMiddleware({ a: (x, next) => next(5) }); // first
c.meta.addMiddleware({ a: (x, next) => next(x * 2) }); // second
c.meta.addMiddleware({ a: (x, next) => next(x + 1) }); // third
c.meta.addMiddleware({ b: 'eser' }); // first
c.meta.addMiddleware({ b: (x, next) => next(x.toUpperCase()) }); // second
c.meta.addMiddleware({ c: 777 }); // first
const p = c.instance;
console.log(`a: ${p.a()}
b: ${p.b()}
c: ${p.c}`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment