【Node middle layer practice (4)】---- logical processing of express middle layer

Foreword: This article is related to learning the practice of Node middle layer. It is recommended that you read the original text of Node middle layer practice
    by Keyon Y. Before starting this article, you can also read the following, Node middle layer practice (1) - full-stack development based on NodeJS , which is helpful for understanding the content of this article. (PS: Node Xiaobai who continues to repay debts ╮(╯▽╰)╭) The     logical processing of express is divided into two parts: forwarding back-end interface and middleware .

1. Forwarding backend interface

The interfaces provided by the backend are divided into two categories:

  • The data interface used to render the page;
  • The request interface for the front-end part to send an ajax request

Data interface

It is the page that can be accessed by the URL link.
First use router.get() to register the route. In the route, first access the backend through axios to obtain the page data response, return a custom object through res.render(), and pass the response as an object attribute to the pug template page. In the pug The response can be used freely on the page.
config/routes/default.js file:

// 首页
router.get('/', addUser, (req, res, next) => {
    
    
	axios.all([
		axios.get('/Api/Carous'),
		axios.get('/Api/Cars/Top10', {
    
    params: {
    
    page: req.query.page || 1}}),
	])
		.then(axios.spread(function (res1, res2){
    
    
			config.throwError(next, res1, res2);
			var page = req.query.page || 1;
			res.render('Default/index', {
    
    
				title: config.title('首页'),
				keywords: config.keywords,
				description: config.description,
				menuNav: 0,
				carList: res1.data.Data,
				top10: res2.data.Data.slice((page-1)*3,page*3)
			});
		})).catch(e => {
    
    
		config.renderError(req, res, e);
	})
});

request interface

It is the interface for the front end to send ajax requests.
The difference with the data interface is that the middle layer only does two things:

  • Use axios to forward the request from the front end to the back end;
  • Using res.send(), forward the response to the backend to the frontend.
// get请求
router.get('/User/Role', (req, res, next) => {
    
    
    axios.get(config.origin + '/Api/User/Role', config.axiosHeaders(req, {
    
    
        params: {
    
    role: req.query.role}
    }))
        .then(res1 => {
    
    
            res.send(res1.data);
        }).catch(e => {
    
    
            config.sendError(res, e);
    })
})

// post请求
router.post('/User/SendRequest', (req, res, next) => {
    
    
	axios.post(config.origin + '/Api/User/SendRequest', {
    
    
		userID: req.body.userID || null,
		requestID: JSON.parse(req.body.requestID) || null
	}, config.axiosHeaders(req))
		.then((res2) => {
    
    
			res.send(res2.data);
		}).catch((e) => {
    
    
		config.sendError(res, e);
	})
});

The post request cannot directly read the request body, and the body-parser dependency needs to be installed

npm i –save body-parser

And mount this dependency in app.js

app.use(bodyParser.urlencoded({
    
    extended: false}));

Get the parameters in the front-end request

Divided into three situations:

  • Get parameters in routes with parameters
router.get('/Cars/:id', (req, res, next) => {
    
    
    axios.get(config.origin + '/Api/Cars', {
    
    
        params: {
    
    role: req.params.id}  // req.params.id获取url中的参数
    }))
    ...
})

  • Get the parameters of the get request
// 例如这样的请求 /Cars/Search?q=tobi
router.get('/Cars/Search', (req, res, next) => {
    
    
    axios.get(config.origin + '/Api/Cars/Search', {
    
    
        params: {
    
    car: req.query.q}  // req.query.q获取参数
    }))
    ...
})

  • Get the parameters of the post request
router.post('/Cars/Search', (req, res, next) => {
    
    
    axios.post(config.origin + '/Api/Cars/Search', {
    
    
        car: req.body.name  // req.body.name获取请求体中的参数
    }))
    ...
})

  • The post request forwards the array object
    express post request. When obtaining an array in the client request, if you directly post an array, express cannot obtain the array. You need to serialize the array on the client and deserialize it in the middle layer:
// 客户端
$.ajax({
    
    
	url: '/Api/Mas/SendInfo',
	type: 'POST',
	data: {
    
    userID: userId, requestID: JSON.stringify(selected)},  // 序列化
	success: function (res) {
    
    
		log(res);
		if(res.Status == 0){
    
    
			$thisModal.hide();
			$('#modal_cds').show();
		}
	}
})
		
// 中间层
axios.post(config.origin + '/Api/Mas/SendInfo', {
    
    
	userID: req.body.userID || null,
	requestID: JSON.parse(req.body.requestID) || null    // 反序列化
}, config.axiosHeaders(req))

2. Middleware

The middle layer should not pass attributes that may not exist

Never pass a property that may not exist in the middle layer!
Do not pass a property that may not exist in the middle layer!
Do not pass a property that may not exist in the middle layer!
Say important things three times, otherwise I don't know where to find the following bugs.

(node:20352) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot read property ‘data’ of undefined

middleware

Express is a web development framework that has minimal functions and is completely composed of routing and middleware: in essence, an Express application is calling various middleware.
Middleware (Middleware) is a function that can access the request object ( request object (req)), the response object ( response object (res)), and the middleware in the request-response loop process in the web application, generally named next variable.
The function code of the middleware:

  • execute any code;
  • Modify request and response objects;
  • Terminate the request-response loop;
  • The next middleware in the call stack.
    If the current middleware does not terminate the request-response loop, the next() method must be called to pass control to the next middleware, otherwise the request will hang.
    Express applications can use the following middleware:
  • application-level middleware
  • Router-level middleware
  • error handling middleware
  • built-in middleware
  • Third-Party Middleware
    Middleware can be mounted at the application level or at the route level using an optional mount path. In addition, you can also mount a series of middleware functions at the same time, thus creating a sub-middleware stack on a mount point.

Use route-level middleware to process request objects

var addUser = require('../../middleware/addUser');
    ...
router.get('/Car/List', addUser, (req, res, next) => {
    
    
    ...
})

addUser is middleware, it is a method that accepts the three parameters req, res, next in the route , and the code must end with **next();**, so that the function pointer is transferred from addUser to (req, res, next ) => {...}.
Using middleware, you can obtain cookies in the request header to verify user login information To
obtain the content of cookies, you need to install cookie-parser dependencies

npm i –save cookie-parser

In app.js, mount this dependency and you can use it.

app.use(cookieParser());

Error Handling Middleware – Error Handle

Pay attention to the order in which the Error Handle is mounted. Generally, it is mounted under app.use() and placed at the end.

var express = require('express');
var cookieParser = require('cookie-parser');
var path = require('path');
var localOptions = require('./build/localOptions');
var config = require('./config/config');
var bodyParser = require('body-parser');
var auth = require('./middleware/auth');
var log4js = require('./config/log4js');

process.env.NODE_ENV = process.env.NODE_ENV ? process.env.NODE_ENV : 'production';
var isDev = process.env.NODE_ENV === 'dev';
var app = express();
var port = config.port;


app.set('view engine', 'pug');
// 设置模板文件路径
if (isDev){
    
    
	app.set('views', path.resolve(__dirname, 'src/Views'));
}else {
    
    
	app.set('views', path.resolve(__dirname, 'dist/Views'));
}

// app.locals定义的键值对能在模板中直接访问
app.locals.env = process.env.NODE_ENV || 'dev';
app.locals.reload = true;

app.use(cookieParser());
app.use(bodyParser.urlencoded({
    
    extended: false}));


if (isDev) {
    
    
    // app.locals.pretty = true;
	// 开发环境,静态文件使用热插拔
	var webpack = require('webpack');
	var webpackDevMiddleware = require('webpack-dev-middleware');
	var webpackHotMiddleware = require('webpack-hot-middleware');
	var webpackDevConfig = require('./build/webpack.dev.config.js');

	var compiler = webpack(webpackDevConfig);
	// 热插拔
	app.use(webpackDevMiddleware(compiler, {
    
    
		publicPath: webpackDevConfig.output.publicPath,
		noInfo: true,
		stats: 'errors-only'
	}))
	app.use(webpackHotMiddleware(compiler, {
    
    
		heartbeat: 1000,
		noInfo: true,
	}));

	// 不能热插拔的往下执行
	var reload = require('reload');
	var http = require('http');
	var server = http.createServer(app);
	// reload(server, app);
	reload(app);
	server.listen(port, () => {
    
    
		console.log('App【dev】 is now running on port ' + port + '!');
	});

	// 静态目录设置必须有,开发环境读取的vendor.js不是内存文件;
    // 静态目录设置必须放在reload后面,避免页面引入reload.js报错
    app.use(express.static(path.join(config.root, 'src')));
    app.use('/', require(path.join(config.configRoot,'/routes')));
	
}else {
    
    
	// 线上环境不需要监听,只需开启node服务即可
	// 设置node的静态文件目录
	app.use(express.static(path.join(config.root, 'dist')));
    app.use('/',require(path.join(config.configRoot,'/routes')));
    // app.listen(process.env.PORT, () => {
    
    
    app.listen(port, () => {
    
    
		console.log('App【production】 is now running on port ' + port + '!');
    })
}

// 捕捉 404错误 传给 error路由
app.use('*', auth, (req, res, next) => {
    
    
	let err = new Error('Not Found');
	err.status = 404;
	next(err);
});

// 捕获 error,跳转至error页面
app.use((err, req, res, next) => {
    
    
	const sc = err.status || 500;
	if(err.status == 405){
    
    
		res.redirect(config.cndesignOrigin + '/Home/GuideAuthentication');
		return;
	}
	res.status(sc);
	// 此处需写入日志
	log4js.error('\r\n Status: '+ sc + "\r\n Message: " + err.message + "\r\n Href: " + localOptions.baseUrl + req.originalUrl + "\r\n User-agent: " + req.headers['user-agent']);

	res.render('Error/404', {
    
    
		error: err,
		status: sc,
		message: err.message,
		userInfo: req.userInfo_ || {
    
     hasLogin: false }
	});
});

reference blog

Node middle layer practice (5) - logic processing of express- middle layer
https://juejin.cn/post/6844904191635226632

Guess you like

Origin blog.csdn.net/qq_26780317/article/details/125848480