当前位置: 首页 > news >正文

在nodejs常见的不良做法及其优化解决方案

在nodejs常见的不良做法及其优化解决方案

当涉及到在expressnodejs中开发应用程序时。遵循最佳实践对于确保项目的健壮性、可维护性和安全性至关重要。

在本文中,我们将探索开发人员经常遇到的几种常见的错误做法,并通过代码示例研究优化的最佳做法,以纠正这些错误。

在本文的结尾,我们将清楚地了解如何避免这些错误并采用最佳最佳实践。

嵌套回调

nodejs早期,开发人员使用嵌套回调处理MongoDB数据库和异步操作。虽然这种方法有效,,但它可以很快导致回调地狱,使代码难以读取和维护。

app.get('/users', (req, res) => {User.find({}, (err, users) => {if (err) {console.log(err);return res.status(500).send('Error occurred');}UserDetails.find({ userId: users[0]._id }, (err, userDetails) => {if (err) {console.log(err);return res.status(500).send('Error occurred');}return res.status(200).json({ users, userDetails });});});
});

这个代码片段演示了嵌套的回调,用于查询用户和他们的详细信息,这些信息来自于使用MongoDB数据库。可以看到管理多个嵌套的回调会变得很麻烦。

不使用嵌套回调,我们可以利用 promiseasync/await 来提高代码可读性和优雅地管理异步操作。

使用promise和async/await

promise提供了一种更整洁的方式来处理异步操作,并使代码更具可读性。下面是同样的例子,使用的是promiseasync/wawit

app.get('/users', async (req, res) => {try {const users = await User.find({});const userDetails = await UserDetails.find({ userId: users[0]._id });return res.status(200).json({ users, userDetails });} catch (err) {console.log(err);return res.status(500).send('Error occurred');}
});

使用async/await消除嵌套结构,大大提高了代码可读性。它提高了代码的可维护性,使错误处理更加简单。

缺乏错误处理

不能正确处理错误会导致意外的崩溃和潜在的安全漏洞。许多开发人员忽略了错误处理,这可能会导致他们的应用程序在使用MongoDB时表现出不可预测的行为。

app.get('/user/:id', (req, res) => {User.findById(req.params.id, (err, user) => {if (err) {console.log(err);// What if an error occurs here? It will be unhandled!}return res.status(200).json(user);});
});

在上面的示例中,如果在对MongoDB数据库查询中发生错误,将不会处理错误,,能导致意外行为或崩溃。为了解决这个问题,必须实施适当的错误处理。

实现错误处理

处理错误的方法建议是使用try/catch代码块:

app.get('/user/:id', async (req, res) => {try {const user = await User.findById(req.params.id);if (!user) {return res.status(404).json({ message: 'User not found' });}return res.status(200).json(user);} catch (err) {console.log(err);return res.status(500).send('Error occurred');}
});

通过使用try/catch块,我们可以捕捉在执行MongoDB查询期间发生的任何错误。此外,我们可以根据特定的错误类型定制错误响应,以向客户端提供信息反馈。

不使用中间件

中间件通过允许开发人员拦截和修改传入的请求,在使用MongoDB 时中间件发挥着至关重要的作用。忽略使用中间件会导致路由膨胀和代码重复。

app.get('/users', (req, res) => {// 一些逻辑// 缺乏中间件使模块化代码和处理通用功能变得困难// 将在不同的路线重复使用更多代码,导致维护问题。
});

使用中间件

中间件允许开发人员集中处理重复任务,提高代码模块化和可维护性。这里有一个使用中间件操作MongoDB 数据库的例子:

const authenticateUser = async (req, res, next) => {try {const user = await User.findById(req.userId);if (!user) {return res.status(401).send('Unauthorized');}req.user = user;return next();} catch (err) {console.log(err);return res.status(500).send('Error occurred');}
};app.get('/users', authenticateUser, (req, res) => {// 现在,这个路由处理程序可以假定用户是经过身份验证的。// 身份验证逻辑已抽象成中间件。// 其他路由也可以重用"认证用户"中间件。return res.status(200).json({ user: req.user });
});

通过利用中间件,我们保持我们的路径清洁,并专注于他们的具体任务。中间件提高了代码的可重用性,简化了调试,并使应用程序更易于管理。

不管理环境变量

在使用 MongoDB数据的应用程序中的敏感信息,如数据库凭证和API键时,不应该在代码栏中硬编码。

const databasePassword = 'mysecretpassword';
const apiKey = 'myapikey';
// 直接在代码中使用敏感信息是不安全的。
// 这些信息最终可能会进入版本控制系统,从而带来安全风险。

将敏感信息直接存储在代码中会使其面临潜在的安全漏洞,并使其难以在不同环境中管理配置。

确保环境变量的安全

为了安全地管理特定环境的配置和敏感数据,我们应该使用类似 dotenv库进行处理。

低效的数据库查询

MongoDB数据库查询效率低下,会导致响应时间慢,并对应用程序性能产生负面影响。通常,开发人员可能不会优化他们的查询,从而导致性能问题。

app.get('/products', (req, res) => {Product.find({}, (err, products) => {if (err) {console.log(err);return res.status(500).send('Error occurred');}return res.status(200).json(products);});
});

在本例中,查询使用MongoDB数据库检索所有产品,对于小型数据集来说,这可能是很好的。然而,随着数据集的增长,这个查询可能变得缓慢且资源密集。

优化数据库查询

为了提高MongoDB数据库查询的性能,开发人员应该专注于查询优化。一种常见的方法是使用select 只检索所需字段的方法:

app.get('/products', async (req, res) => {try {const products = await Product.find({}).select('name price');return res.status(200).json(products);} catch (err) {console.log(err);return res.status(500).send('Error occurred');}
});

只从products 收集数据时,我们减少了数据库和应用程序之间的数据传输量,从而提高了性能。

结论

在本文中,我们探讨了与MongoDB一起使用时的常见不良做法。我们还了解了它们的潜在缺点,并用代码示例探讨了优化的最佳实践,以纠正这些问题。

通过遵循这些最佳实践,可以确保能够带来更加高效、可维护和安全的处理。优先排序代码可读性,优雅地处理错误,并采用中间件更好地模块化。此外,使用dotenv 能更安全地管理敏感数据并优化数据库查询,以提高应用程序性能。

相关文章:

在nodejs常见的不良做法及其优化解决方案

在nodejs常见的不良做法及其优化解决方案 当涉及到在express和nodejs中开发应用程序时。遵循最佳实践对于确保项目的健壮性、可维护性和安全性至关重要。 在本文中,我们将探索开发人员经常遇到的几种常见的错误做法,并通过代码示例研究优化的最佳做法&…...

关于layui upload上传组件上传文件无反应的问题

最近使用layui upload组件时,碰到了上传文件无反应的问题,感到非常困惑。 因为使用layui upload组件不是一次两次了,之前每次都可以,这次使用同样的配方,同样的姿势,为什么就不行了呢? 照例先…...

容器网络之Flannel

​ 第一个问题位置变化,往往是通过一个称为注册中心的地方统一管理的,这个是应用自己做的。当一个应用启动的时候,将自己所在环境的 IP 地址和端口,注册到注册中心指挥部,这样其他的应用请求它的时候,到指挥…...

SVM(下):如何进行乳腺癌检测?

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们点赞👍🏻、收藏⭐️、…...

嵌入式Linux应用开发-第十五章具体单板的按键驱动程序

嵌入式Linux应用开发-第十五章具体单板的按键驱动程序 第十五章 具体单板的按键驱动程序(查询方式)15.1 GPIO操作回顾15.2 AM335X的按键驱动程序(查询方式)15.2.1 先看原理图确定引脚及操作方法15.2.2 再看芯片手册确定寄存器及操作方法15.2.3 编程15.2.3.1 程序框架15.2.3.2 硬…...

MySQL体系结构和四层架构介绍

MySQL体系结构图如下: 四层介绍 1. 连接层: 它的主要功能是处理客户端与MySQL服务器之间的连接(比如Java应用程序通过JDBC连接MySQL)。当客户端应用程序连接到MySQL服务器时,连接层对用户进行身份验证、建立安全连接并管理会话状态。它还处理…...

【产品运营】如何做好B端产品规划

产品规划是基于当下掌握的多维度信息,为追求特定目的,而制定的产品资源投入计划。 产品规划是基于当下掌握的多维度信息(客户需求、市场趋势、竞争对手、竞争策略等),为追求特定目的(商业增长、客户满意等&…...

ruoyi-启动

1 springboot 版本 git 地址 ruoyi-vue-pro: 🔥 官方推荐 🔥 RuoYi-Vue 全新 Pro 版本,优化重构所有功能。基于 Spring Boot MyBatis Plus Vue & Element 实现的后台管理系统 微信小程序,支持 RBAC 动态权限、数据权限…...

select完成服务器并发

服务器 #include <myhead.h>#define PORT 4399 //端口号 #define IP "192.168.0.191"//IP地址//键盘输入事件 int keybord_events(fd_set readfds); //客户端交互事件 int cliRcvSnd_events(int , struct sockaddr_in*, fd_set *, int *); //客户端连接事件 …...

初级篇—第四章聚合函数

文章目录 聚合函数介绍聚合函数介绍COUNT函数AVG和SUM函数MIN和MAX函数 GROUP BY语法基本使用使用多个列分组WITH ROLLUP HAVING基本使用WHERE和HAVING的对比开发中的选择 SELECT的执行过程查询的结构SQL 的执行原理 练习流程函数 聚合函数介绍 聚合函数作用于一组数据&#x…...

计算机图像处理-中值滤波

非线性滤波 非线性滤波是利用原始图像跟模版之间的一种逻辑关系得到结果&#xff0c;常用的非线性滤波方法有中值滤波和高斯双边滤波&#xff0c;分别对应cv2.medianBlur(src, ksize)方法和cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])方法。 …...

Golang中的包和模块设计

Go&#xff0c;也被称为Golang&#xff0c;是一种静态类型、编译型语言&#xff0c;因其简洁性和对并发编程的强大支持而受到开发者们的喜爱。Go编程的一个关键方面是其包和模块系统&#xff0c;它允许创建可重用、可维护和高效的代码。本博客文章将深入探讨在Go中设计包和模块…...

web:[极客大挑战 2019]Upload

题目 页面显示为一个上传&#xff0c;猜测上传一句话木马文件 先查看源代码看一下有没有有用的信息&#xff0c;说明要先上传图片&#xff0c;先尝试上传含有一句话木马的图片 构造payload <?php eval($_POST[123]);?> 上传后页面显示为&#xff0c;不能包含<&…...

ICMP差错包

ICMP报文分类 Type Code 描述 查询/差错 0-Echo响应 0 Echo响应报文 查询 3-目的不可达 0 目标网络不可达报文 差错 1 目标主机不可达报文 差错 2 目标协议不可达报文 差错 3 目标端口不可达报文 差错 4 要求分段并设置DF flag标志报文 差错 5 源路由…...

算法基础课第二部分

算法基础课 第四讲 数学知识AcWing1381. 阶乘(同余&#xff0c;因式分解) 质数AcWing 866. 质数的判定---试除法AcWing 868. 质数的判定---埃氏筛AcWing867. 分解质因数---试除法AcWing 197. 阶乘---分解质因数---埃式筛 约数AcWing 869. 求约数---试除法AcWing 870. 约数个数-…...

【数据结构】外部排序、多路平衡归并与败者树、置换-选择排序(生成初始归并段)、最佳归并树算法

目录 1、外部排序 1.1 基本概念 1.2 方法 2、多路平衡归并与败者树 2.1 K路平衡归并 2.2 败者树 3、置换-选择排序&#xff08;生成初始归并段&#xff09;​编辑 4、最佳归并树 4.1 理论基础​编辑 4.2 构造方法 ​编辑 5、各种排序算法的性质 1、外部排序 1.1 基本概…...

抽象工厂模式 创建性模式之五

在看这篇文章之前&#xff0c;请先看看“简单工厂模式”和“工厂方法模式”这两篇博文&#xff0c;会更有助于理解。我们现在已经知道&#xff0c;简单工厂模式就是用一个简单工厂去创建多个产品&#xff0c;工厂方法模式是每一个具体的工厂只生产一个具体的产品&#xff0c;然…...

servlet如何获取PUT和DELETE请求的参数

1. servlet为何不能获取PUT和DELETE请求的参数 Servlet的规范是POST的数据需要转给request.getParameter*()方法&#xff0c;没有规定PUT和DELETE请求也这么做 The Servlet spec requires form data to be available for HTTP POST but not for HTTP PUT or PATCH requests. T…...

【Vue.js】使用Element中的Mock.js搭建首页导航左侧菜单---【超高级教学】

一&#xff0c;Mock.js 1.1 认识Mock.js Mock.js是一个用于前端开发中生成随机数据、模拟接口响应的 JavaScript 库。模拟数据的生成器&#xff0c;用来帮助前端调试开发、进行前后端的原型分离以及用来提高自动化测试效率 总结来说&#xff0c;Element中的Mock.js是一个用于…...

从技术创新到应用实践,百度智能云发起大模型平台应用开发挑战赛!

大模型已经成为未来技术发展方向的重大变革&#xff0c;热度之下更需去虚向实&#xff0c;让技术走进产业场景。在这样的背景下&#xff0c;百度智能云于近期发起了“百度智能云千帆大模型平台应用开发挑战赛”。 挖掘大模型落地应用 千帆大模型平台应用开发挑战赛启动 在不久前…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...