Node后端框架Express与Koa接口统一响应封装

news2024/11/24 15:40:01

背景

以前在写 SpringBoot 全栈开发的系列文章中全栈开发之后端脚手架:SpringBoot集成MybatisPlus代码生成,分页,雪花算法,统一响应,异常拦截,Swagger3接口文档,有提到对后端接口的响应数据进行统一的封装,方便前端或者第三方进行数据获取与对接工作;统一响应一般包含状态码、消息内容、数据内容等。

这里对 2017 年写的一个基于 Node.jsExpress.js 框架开发的后端项目的接口进行类似的封装。

通用状态码与信息封装

/**
 * @author ycx
 * @description 业务异常通用code
 *
 */
class BaseResultCode {
    /***********************************/
    /**
     * code
     */
    code;
    /**
     * 说明
     */
    desc;

    constructor(code, desc) {
        this.code = code;
        this.desc = desc;
    }

    /************************************/
    static SUCCESS = new BaseResultCode(200, '成功');
    static FAILED = new BaseResultCode(500, '失败');
    static VALIDATE_FAILED = new BaseResultCode(400, '参数校验失败');
    static API_NOT_FOUNT = new BaseResultCode(404, '接口不存在');
    static API_BUSY = new BaseResultCode(429, '操作过于频繁')
}

module.exports = BaseResultCode

Note: 上面的 class 写法对 Node.js 的版本有要求, 10.x 报错, 12.x 可以使用。

2023-12-10-Response.jpg

统一响应封装

const ResultCode = require('./BaseResultCode');
/**
 * @author ycx
 * @description 统一返回结果
 */
class Result {
    /**
     * 返回code
     */
    code;
    /**
     * 返回消息
     */
    msg;
    /**
     * 返回数据
     */
    data;
    /**
     * 返回时间
     */
    time;

    /**
     * 
     * @param code {number} 返回code
     * @param msg {string} 返回消息
     * @param data {any} 返回具体对象
     */
    constructor(code, msg, data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
        this.time = Date.now();
    }

    /**
     * 成功
     * @param data {any} 返回对象
     * @return {Result}
     */
    static success(data) {
        return new Result(ResultCode.SUCCESS.code, ResultCode.SUCCESS.desc, data);
    }

    /**
     * 失败
     */
    static fail(errData) {
        return new Result(ResultCode.FAILED.code, ResultCode.FAILED.desc, errData);
    }

    /**
     * 参数校验失败
     */
    static validateFailed(param) {
        return new Result(ResultCode.VALIDATE_FAILED.code, ResultCode.VALIDATE_FAILED.desc, param);
    }

    /**
     * 拦截到的业务异常
     * @param bizException {BizException} 业务异常
     */
    static bizFail(bizException) {
        return new Result(bizException.code, bizException.msg, null);
    }
}
module.exports = Result

返回数据时进行封装

封装好统一的响应后,在 Express.js 后端项目中怎么使用?先是引入: const Result = require("../common/Result"); ,然后直接使用 Result.success() 或者 Result.fail() 返回数据或错误信息。

2023-12-10-Usage.jpg

const router = express.Router();
const Result = require("../common/Result");

router.get("/:productName/:deviceName", function(req, res) {
    let productName = req.params.productName;
    let deviceName = req.params.deviceName;
    Device.findOne({
        "product_name": productName,
        "device_name": deviceName
    }, function(err, device) {
        if (err) {
            res.send(Result.fail(err));
        } else {
            if (device != null) {
                Connection.find({
                    device: device._id
                }, function(_, connections) {
                    res.json(Result.success(Object.assign(device.toJSONObject(), {
                        connections: connections.map(function(conn) {
                            return conn.toJSONObject();
                        })
                    })))
                })
            } else {
                res.status(404).json({
                    error: "Not Found"
                });
            }
        }
    })
});
router.put("/:productName/:deviceName/suspend", function(req, res) {
    let productName = req.params.productName
    let deviceName = req.params.deviceName
    Device.findOneAndUpdate({
        "product_name": productName,
        "device_name": deviceName
    }, {
        status: "suspended"
    }, {
        useFindAndModify: false
    }).exec(function(err, device) {
        if (err) {
            res.send(Result.fail(err));
        } else {
            if (device != null) {
                device.disconnect();
            }
            res.status(200).send(Result.success("ok"));
        }
    })
});

Note:顺便在这里简单总结下 Express.js 获取请求参数的几种方法:

  1. req.query.productName,对应http://localhost:3000/device?productName=product
  2. req.params.productName,对应http://localhost:3000/device/:productName
  3. req.headers[“productname”],获取头信息中的参数,注意小写~
  4. req.body.productName,Express.js无法直接获取Post请求的参数,需要设置body解析中间件,app.use(express.urlencoded())

可能遇到的问题

Express 请求没有响应 日志显示:-- ms

原因:在响应时没有调用 res.send() 或者 next() 向下执行,导致最终没有结果返回给调用方。

router.put("/:productName/:deviceName/suspend", function(req, res) {
    let productName = req.params.productName
    let deviceName = req.params.deviceName
    Device.findOneAndUpdate({
        "product_name": productName,
        "device_name": deviceName
    }, {
        status: "suspended"
    }, {
        useFindAndModify: false
    }).exec(function(err, device) {
            if (err) {
                res.send(err));
        } else {
            if (device != null) {
                device.disconnect();
            }
            Result.success("ok");
        }
    })
});

解决方法: 将 Result.success 放到 res.send() 里,就像这样: res.send(Result.success("ok"))

结果展示

2023-12-10-Result.jpg

小总结

上述内容记录了对 Node.js 后端框架 Express.js (如果使用的是 Koa.js ,方法也类似)的接口进行统一响应封装的方法以及可能遇到的问题,后端开发时,对响应和异常进行统一封装有几个好处:

  1. 统一风格:通过封装,可以确保所有的响应和异常都遵循相同的格式和风格,使代码更加一致和易于理解。
  2. 便于维护:统一封装可以让你更容易地管理和维护响应和异常的逻辑,而不必在每个地方都重复相同的代码。
  3. 安全性:通过封装异常,可以更好地处理错误情况,确保系统的安全性和稳定性。
  4. 易于扩展:封装可以让你更容易地扩展和修改响应和异常的处理逻辑,而不必改动大量的代码。

总之,统一封装可以提高代码的可维护性、安全性和可扩展性,这是在进行 HTTP 接口开发时的一个最佳实践。

Reference

  • code笔记:nodeJS框架 express 接口统一返回结果设计

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1307610.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flink找不到隐式项

增加 import org.apache.flink.streaming.api.scala._ 即可

逆向思考 C. Fence Painting

Problem - 1481C - Codeforces 思路:逆序考虑,因为每一块木板都是被最后一次粉刷所决定的。 从后往前开始,对于 c i c_i ci​来说, 如果这个颜色还有没有涂的木板,那么涂到其中一个木板即可如果这个颜色下没有未涂的…

2024最新软件测试八股文,能不能拿心仪Offer就看你背得怎样了

前言 鉴于目前测试就业越来越严峻,内卷也成了测试领域的代名词了。我的一个HR朋友告诉我,由于门槛较低,现在普通测试岗(偏功能)的投递比已经将近100,也就是一个岗位差不多有百分简历投进来。 所以现在还想…

云原生之深入解析OOM和CPU节流

一、前言 使用 Kubernetes 时,内存不足 (OOM) 错误和 CPU 节流是云应用程序中资源处理的主要难题,这是为什么呢?云应用程序中的 CPU 和内存要求变得越来越重要,因为它们与云成本直接相关。通过 limits 和 requests ,可…

表单参数绑定(如何解决一个输入框绑定两个参数)

表单参数绑定(如何解决一个输入框绑定两个参数) 问题复现 <el-form-item label"会议编号" prop"meetingNum"><el-select v-model"form.meetingNum" placeholder"请选择会议编号" style"width: 100%;":disabled&quo…

C语言:高精度除法(除低精度)

P1480 A/B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 由图知&#xff0c;被除数的上一位的余数乘10加这位就是这一位结果的除数。 c[i] (d * 10 a[i]) / b #include<stdio.h> #include<string.h> char x[50005];//存储被除数&#xff0c;转为字符…

leetcode 30. 串联所有单词的子串(优质解法)

代码&#xff1a; class Solution {public static List<Integer> findSubstring(String s, String[] words) {List<Integer> integerListnew ArrayList<>();int lengthwords.length; //words 数组中的字符串个数int sizewords[0].length(); //words 数组…

Oracle数据库对SAP的支持

其实有时候&#xff0c;很多信息都已经整理好了&#xff0c;你只需要知道他在哪里就好&#xff0c;无需自己整理。 Oracle数据库对SAP的支持&#xff0c;可以从这个网页快速了解。 看前面的概述&#xff1a; Oracle 数据库是全球 SAP 客户中排名第一的数据库&#xff0c;拥有…

Spring上IOC之@EnableAspectJAutoProxy

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

初识人工智能,一文读懂贝叶斯优化和其他算法的知识文集(8)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

【深度学习】PHP操作mysql数据库总结

一.PHP数据库的扩展分类 1.MySQL 扩展是针对 MySQL 4.1.3 或更早版本设计的&#xff0c;是 PHP 与 MySQL数据库交互的早期扩展。由于其不支持 MySQL 数据库服务器的新特性&#xff0c;且安全性差&#xff0c;在项目开发中不建议使用&#xff0c;可用 MySQLi 扩展代替。 2.MySQ…

LeetCode 1457. 二叉树中的伪回文路径||位运算 DFS

1457. 二叉树中的伪回文路径 给你一棵二叉树&#xff0c;每个节点的值为 1 到 9 。我们称二叉树中的一条路径是 「伪回文」的&#xff0c;当它满足&#xff1a;路径经过的所有节点值的排列中&#xff0c;存在一个回文序列。 请你返回从根到叶子节点的所有路径中 伪回文 路径的…

记一次docker的overlay2目录占用大量磁盘空间

1、报错 Linux服务器报错磁盘没空间了&#xff1a; no space left on device2、排错 从根目录看下哪个目录有问题&#xff1a; cd / du -sh * # s即只显示总和&#xff0c;h即显示人类可读格式&#xff0c;就是数字单位的格式目录有点多&#xff0c;sort排序下&#xff1a;…

数学learning

目录 移动平均 简单移动平均 加权移动平均 指数移动平均 矩阵求导 矩阵对标量求导 Matrix-by-scalar 标量对矩阵求导 Scalar-by-matrix 参考博客 移动平均 优化算法里面会涉及到一个知识点&#xff1a;指数移动平均。 但是为了知识的完整性&#xff0c;这里会将常见的移动…

容器技术与操作系统

文章目录 容器技术 vs 虚拟机操作系统容器 Docker与操作系统 容器技术 vs 虚拟机 操作系统 操作系统是一个很重而且很笨的程序&#xff0c;简称笨重&#xff0c;有多笨重呢&#xff1f; 操作系统运行起来是需要占用很多资源的&#xff0c;大家对此肯定深有体会&#xff0c;刚…

ARM day8

1.题目&#xff1a;主机获取从机里面的温湿度数据&#xff0c;并打印出来 结果&#xff1a; 代码&#xff1a; main.c #include "iic.h"#include "si7006.h"void delay(int ms){int i,j;for(i0;i<ms;i){for(j0;j<2000;j);}}int main(){short tem;…

【Linux】锁的简单封装以及原理解析

文章目录 一、锁的原理过程1&#xff1a;过程2过程3过程4 二、 锁的简单封装1.LockGuard.hpp2.使用1.正常锁的使用2.使用封装后的 总结 一、锁的原理 为了实现互斥锁操作,大多数体系结构都提供了swap或exchange指令,该指令的作用是把寄存器和内存单元的数据相交换,由于只有一条…

基于ssm社区管理与服务的设计与实现论文

目录 摘 要 1 Abstract 2 第一章 绪论 3 1.1研究背景 3 1.2 研究现状 3 1.3 研究内容 4 第二章 系统关键技术 5 2.1 Java简介 5 2.2 MySql数据库 5 2.3 B/S结构 6 2.4 Tomcat服务器 6 第三章 系统分析 7 3.1可行性分析 7 3.1.1技术可行性 7 3.1.2经济可行性 7 3.1.3运行可行性…

IP代理检测:判断IP质量优劣要注意的5件事

使用代理是各种在线活动的常见做法&#xff0c;但确保其质量对于避免潜在问题并确保无缝体验至关重要。 在本文中&#xff0c;我们深入探讨进行彻底代理检查以保证可靠性和安全性的基本方面。 1. 验证地理位置信息 评估代理时的主要考虑因素之一是其地理位置&#xff0c;这也…

自动化补丁管理软件

什么是自动化补丁管理 自动补丁管理&#xff08;或自动补丁&#xff09;是指整个补丁管理过程的自动化&#xff0c;从扫描网络中的所有系统到检测缺失的补丁&#xff0c;在一组测试系统上测试补丁&#xff0c;将它们部署到所需的系统&#xff0c;并提供定期更新和补丁部署状态…