node.js onion ring model and simple implementation of Middleware

middleware

preface

Recently, in the process of learning node.js, I found that there are many trivial details to be completed in the actual project. For developers, developers only need to pay attention to the business development without touching so many details, so as to improve the development efficiency. At this time, we will introduce middleware.

meaning

The previous definition of middleware is computer software that provides services for application software on the operating system. It is neither the operating system nor the application software, but for the application software to use the underlying services better and more conveniently.

Now, the meaning of Middleware in node.js is to encapsulate the middleware for detailed processing of HTTP requests, which is a way to encapsulate functions, so that developers can break away from these details and focus on business.

Middleware is like a filter, that is, let the filter handle it before entering the specific business. Then respond.

Middleware model

Each middleware deals with relatively simple logic, and multiple are combined to finally form a strong framework foundation!

Define Middleware

We need to provide a mechanism to notify the next middleware to execute after the current middleware processing is completed. This is done recursively. After TODO is executed, inform the next middleware to execute through next(). If the next function is not called, the request is terminated in the middleware.

//Define Middleware
const m1 = function (req, res, next) {
    //TODO
    next()
}

const m2 = function (req, res, next) {
    //TODO
    next()
}

//Middleware collection
const middlewares = [m1, m2]

//Define the method of executing Middleware
function useApp (req, res) {
  const next = () => {
    // Get the first Middleware
    const middleware = middlewares.shift()
    if (middleware) {
      middleware(req, res, next)
    }
  }
  next()
}
//implement
useApp()

After the first middleware is executed here, call next() to execute the next middleware. In this way, all intermediate will be executed, and the request to response will not stop.

That's the problem. What if some middleware is asynchronous? The new feature of es7, async await, will be used in koa2, so that the middleware method can be changed to

//Define Middleware
const m1 = async (req, res, next) {
    //TODO
    await next()
}

const m2 = function (req, res, next) {
    //TODO
    await next()
}

Note that in this case, the value of the middleware becomes Promise object through async await, and the method of executing the middleware also needs to be changed.

//Define the method of executing Middleware
function useApp (req, res) {
  const next = () => {
    // Get the first Middleware
    const middleware = middlewares.shift()
    if (middleware) {
      Promise.resolve(middleware(req, res, next))
    }
  }
  next()
}

The asyn await method used in koa2 uses middleware to enjoy the onion model of koa2

Write a middleware yourself

After understanding the middleware, write a middleware. The middleware encapsulates the return value format, so that developers don't have to worry about the return value format.

//Return value Middleware
const response = () => {
    return async (ctx, next) => {
        ctx.empty = arr => {
            var isnull = []
            const req = ctx.request.method == "POST" ? ctx.request.body : ctx.query
            for (let item of arr) {
                if (!req[item]) {
                    isnull.push(item)
                }
            }
            if (isnull.length) {
                ctx.body = { code: -1, msg: 'Missing parameter' + isnull.join(",") }
                return true
            }
            return false
        }
        ctx.suc = (msg, data) => {
            ctx.body = { code: 1, msg, data }
        }
        ctx.err = (msg, err) => {
            ctx.body = { code: -1, msg, err: err ? err.toString() : '' }
        }
        await next()
    }
}

module.exports = response

Then reference the secondary Middleware in app.js

app.use(response())

When implementing business functions, you can directly use the intermediate defined above,

ctx.empty: judge whether the parameters are complete,

ctx.suc: format of return value upon success

ctx.err: format returned on failure

summary

Through these middleware, we unconsciously simplify complex things.

Tags: Python Javascript node.js

Posted on Mon, 27 Sep 2021 21:14:01 -0400 by puREp3s+