After understanding the use of Express in the previous article, I will summarize the simple implementation principle of Express middleware.
We know that Express middleware is a function by function, so how to make these functions execute orderly? We need to call the next function. In fact, the next function calls the next middleware function.
The following code implements the simple app.use registration middleware, as well as the get and post middleware. The same is true for middleware implementation of other request modes
Core code:
const next = () => { const stack = stacks.shift() if(stack) { stack(req, res, next) } } next()
stacks is an array queue that holds all the middleware functions that meet the rules. Follow the first in, first out principle. That is, the first registered middleware function is executed first.
Implementation code
const http = require('http') const slice = Array.prototype.slice class Express { constructor() { this.router = { all: [], // Match all middleware functions get: [], post: [] } } /** * Integrate middleware here * @param {string} path * @returns {object} */ middlewareHandler(path) { const info = {} if (typeof path === 'string') { info.path = path info.stack = slice.call(arguments, 1) // Middleware array } else { info.path = '/' info.stack = slice.call(arguments, 0) } return info } use() { const allStack = this.middlewareHandler(...arguments) this.router.all.push(allStack) } get() { const getStack = this.middlewareHandler(...arguments) this.router.get.push(getStack) } post() { const postStack = this.middlewareHandler(...arguments) this.router.post.push(postStack) } /** * * @param {string} method * @param {string} url * @returns {Array} */ accordStack(method, url) { let stacks = [] stacks = stacks.concat(this.router.all) stacks = stacks.concat(this.router[method]) return stacks .filter(stack => { return url.indexOf(stack.path) !== -1 }).map(item => item.stack[0]) } handler(req, res, stacks) { // Function expression const next = () => { const stack = stacks.shift() if(stack) { stack(req, res, next) } } next() } callback() { return (req, res) => { res.json = data => { res.setHeader('Content-Type', 'application/json') res.end(JSON.stringify(data)) } // Get the request method and url, and filter the middleware functions const {method, url} = req const stacks = this.accordStack(method.toLowerCase(), url) this.handler(req, res, stacks) } } listen(...args) { const server = http.createServer(this.callback()) server.listen(...args) } } // Factory mode, export an instance object module.exports = () => { return new Express() }