Skip to content

Instantly share code, notes, and snippets.

@zazaulola
Last active September 8, 2021 01:36
Show Gist options
  • Save zazaulola/dc732acc250c63ec41e2298937693f92 to your computer and use it in GitHub Desktop.
Save zazaulola/dc732acc250c63ec41e2298937693f92 to your computer and use it in GitHub Desktop.
Primitive middleware router without timeout
// Router is a function that returns async function.
const Router = (...chain) =>
Object.assign(
// That async function as object have one method push()
async (ctx) => {
// When it calls that function it runs recursive algorithm
return await (async function run(idx) {
// Which calls each function in the chain
let res = await ("AsyncFunction" !== chain[idx].constructor.name
? new Promise((res) => chain[idx](ctx, res))
: chain[idx](ctx));
// If it returns any result it will terminate chain execution
return undefined != res
? res
: idx < chain.length - 1
? await run(idx + 1)
: undefined;
})(0);
},
{ push: (...mws) => chain.push(...mws) }
);
// Examples of use
let router = Router();
// Each middleware is a function with 2 arguments
// first of it is context object
// second of it is callback
router.push((ctx, next) => {
console.log(1);
ctx.x++;
// call of the callback pass execution to next middleware
next();
});
let router2 = Router();
// We can use async function as middleware
router2.push(async (ctx) => {
console.log(2);
ctx.x++;
});
router2.push((ctx, next) => {
console.log(3);
ctx.x++;
next();
//second call of the callback will be ignored
setTimeout(() => next(), 1000);
});
// And we can use other router as middleware
router.push(router2);
router.push((ctx, next) => {
console.log(4);
ctx.x++;
setTimeout(next, 500);
});
router.push((ctx, next) => {
console.log(5);
ctx.x++;
next();
//second call of the callback will be ignored
next(true);
});
router.push(async (ctx) => {
console.log(6);
ctx.x++;
// We can terminate chain execution
// if we return any other value except undefined
return undefined;
});
router.push((ctx, next) => {
console.log(7);
ctx.x++;
// terminate chain execution
next(true);
});
// that middleware will never be called
router.push((ctx, next) => {
console.log(8);
ctx.x++;
next();
});
(async () => {
let ctx = { x: 0 };
let res = await router(ctx);
console.log("End");
console.log("x=", ctx.x, "ctx=", ctx);
console.log(res);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment