作为开发人员,我们都努力争取易于理解,修改和扩展的高效且稳健的代码库。通过采用最佳实践并探索先进的技术,我们可以释放Nodejs的真正潜力,并显着提高应用程序的质量。在此博客中,我们将重点介绍Nodejs的五种高级技术。因此,固定安全带并准备好探索它们。
1.添加中间件
使用使用方法将中间软件添加到每个路由中,而是将其添加到路由列表的顶部。这样,在到达各自的路线处理程序之前,中间件下面定义的任何路线都会自动通过中间件。
const route = express.Router();
const {login} = require("../controllers/auth");
route.get('/login', login)
// isAuthenticated is middleware that checks whether
// you are authenticated or not
// // ❌ Avoid this: middleware on each route
route.get('/products', isAuthenticated, fetchAllProducts);
route.get('/product/:id', isAuthenticated, getProductById)
// ✅ Instead, do this
// Route without middleware
route.get('/login', login)
// Middleware function: isAuthenticated
// This will be applied to all routes defined after this point
route.use(isAuthenticated);
// Routes that will automatically check the middleware
route.get('/products', fetchAllProducts);
route.get('/product/:id', getProductById);
这种方法有助于保持代码的组织,并避免单独重复每个路线的中间件。
2.使用全局错误处理
我们可以使用nodejs全局错误处理功能,而不是在每个控制器上构建错误响应。首先,创建一个从内置错误类派生的自定义apperror类。此自定义类允许您自定义错误对象,并具有其他属性,例如状态代码和状态。
// Custom Error class
module.exports = class AppError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
this.status = statusCode < 500 ? "error" : "fail";
Error.captureStackTrace(this, this.constructor);
}
};
创建自定义错误类后,在根路由器文件中添加全局错误处理程序中间件。此中间软件功能需要四个参数(ERR,REQ,RES,下一个),并在整个应用程序中处理错误。在全局错误处理程序中,您可以根据错误对象的状态代码,状态和消息属性格式化错误响应。您可以自定义此响应格式以满足您的需求。此外,包括用于开发环境的堆栈属性。
// Express setup
const express = require('express');
const app = express();
app.use('/', (req, res) => {
res.status(200).json({ message: "it works" });
});
app.use('*', (req, res) => {
res.status(404).json({
message: `Can't find ${req.originalUrl} this route`,
});
});
// 👇 add a global error handler after all the routes.
app.use((err, req, res, next) => {
err.status = err.status || "fail";
err.statusCode = err.statusCode || 500;
res.status(err.statusCode).json({
status: err.status,
message: transformMessage(err.message),
stack: process.env.NODE_ENV === "development" ? err.stack : undefined,
});
});
添加它后,您可以使用Next(新Apperror(消息,状态代码))丢弃错误。下一个功能会自动将错误传递给全局错误处理程序中间件。
// inside controllers
// route.get('/login', login);
exports.login = async (req, res, next) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email }).select("+password +lastLoginAt");
if (!user || !(await user.correctPassword(password, user.password))) {
// 👇 like this
return next(new AppError("Invalid Email / Password / Method", 404));
}
// Custom logic for generating a token
const token = 'generated_token';
res.status(200).json({ token });
} catch(error) {
next(error
}
});
总的来说,这种方法通过将其集中到一个地方来简化错误处理,从而更容易在应用程序上维护和自定义错误响应。
3.使用自定义的尝试捕获功能
我们可以使用实现相同目的的自定义函数,而不是用一个try-catch块手动包装每个控制器功能。
// ❌ Avoid this
// Using try-catch block each controllers
exports.login = async (req, res, next) => {
try {
// logic here
} catch(error) {
res.status(400).json({ message: 'You error message'}
}
});
TryCatchFN函数接受一个函数(FN)作为输入,并返回一个新功能,将原始函数用Try-Catch块包装。如果包装函数中发生错误,则使用捕获方法捕获,并且该错误将传递给由全局错误处理程序处理的下一个函数。
// ✅ Instead, do this
const tryCatchFn = (fn) => {
return (req, res, next) => {
fn(req, res, next).catch(next);
};
}
// To use this custom function, you can wrap your controller
// functions with tryCatchFn:
exports.login = tryCatchFn(async (req, res, next) => {
// logic here
});
通过将控制器函数用TryCatchFN包裹,您确保将自动捕获这些功能中的任何错误并将其传递给全局错误处理程序,从而消除了单独添加try-catch块的需要。
>这种方法有助于以更清洁,更简洁的方式集中错误处理,使您的代码更加可维护和减少重复性错误处理代码。
4.将主文件分为两个部分。
使用Express开发NodeJS应用程序时,通常拥有包含所有业务逻辑,路由定义和服务器设置的主文件。但是,随着应用程序的增长,管理和维护一个处理所有内容的文件可能变得困难。
解决此问题并保持代码库清洁器和更有条理的一种建议技术是将主文件分为两个部分:一个用于路线,另一个用于服务器设置或配置。这是一个例子:
// app.js
const express = require('express');
const app = express();
/* Middlewares */
app.get('/', (req, res) => {
res.status(200).json({ message: "it works" });
})
app.use(/* Global Error Handler */);
module.exports = app;
// server.js
const app = require('./app');
const port = process.env.PORT || 5001;
app.listen(port, () => console.log('Server running at', port));
5.与控制器的单独路线
要获得一个更有条理的模块化代码库,我建议将路线与控制器分开。这种做法有助于保持清晰的关注点,并提高代码的可读性和可维护性。这是一个证明路线和控制器分离的示例。
// ❌ Avoid this
const route = express.Router();
route.get('/login', tryCatchFn(req, res, next) => {
// logic here
}))
// ✅ Do this
const route = express.Router();
const {login} = require("../controllers/auth");
route.get('/login', login);
结论
在本文中,我们讨论了不同的高级技术来编写干净易于维护的Nodejs代码。有许多最佳实践可以大大提高应用程序代码的质量。随时探索这些技术并将它们应用它们来增强您的代码库。
希望您能觉得这篇文章很有趣。
保持好奇;保持编码!