93 # 实现 express 错误处理中间件

这篇具有很好参考价值的文章主要介绍了93 # 实现 express 错误处理中间件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

上一节实现了 express 的中间件,这一节来实现错误处理中间件

执行某一步出错了,统一规定调用 next 传递的参数就是错误信息

先看 express 实现的demo

const express = require("express");
const app = express();

app.use("/", (req, res, next) => {
    console.log("中间件1");
    // next();
    next("中间件1出错了");
});

app.use("/", (req, res, next) => {
    console.log("中间件2");
    next();
    // next("中间件2出错了");
});

app.use("/", (req, res, next) => {
    console.log("中间件3");
    next();
    // next("中间件3出错了");
});

app.get(
    "/",
    (req, res, next) => {
        console.log("路由1");
        next();
    },
    (req, res, next) => {
        res.end("出错了 *****");
    }
);

app.listen(3000, () => {
    console.log(`server start 3000`);
    console.log(`在线访问地址:http://localhost:3000/`);
});

然后去访问:http://localhost:3000/

93 # 实现 express 错误处理中间件,Node / Node 框架,前端工程架构,express,中间件

错误处理中间价,里面必须要有 4 个 参数(取函数的长度),放到栈的最底下

app.use((err, req, res, next) => {
    res.end(err);
})

93 # 实现 express 错误处理中间件,Node / Node 框架,前端工程架构,express,中间件

下面实现处理逻辑

router/index.js

const url = require("url");
const Route = require("./route");
const Layer = require("./layer");
const methods = require("methods");

function Router() {
    // 维护所有的路由
    this.stack = [];
}

Router.prototype.route = function (path) {
    // 产生 route
    let route = new Route();
    // 产生 layer 让 layer 跟 route 进行关联
    let layer = new Layer(path, route.dispatch.bind(route));
    // 每个路由都具备一个 route 属性,稍后路径匹配到后会调用 route 中的每一层
    layer.route = route;
    // 把 layer 放到路由的栈中
    this.stack.push(layer);
    return route;
};

methods.forEach((method) => {
    Router.prototype[method] = function (path, handlers) {
        // 1.用户调用 method 时,需要保存成一个 layer 当道栈中
        // 2.产生一个 Route 实例和当前的 layer 创造关系
        // 3.要将 route 的 dispatch 方法存到 layer 上
        let route = this.route(path);
        // 让 route 记录用户传入的 handler 并且标记这个 handler 是什么方法
        route[method](handlers);
    };
});

Router.prototype.use = function (path, ...handlers) {
    // 默认第一个是路径,后面是一个个的方法,路径可以不传
    if (typeof path === "function") {
        handlers.unshift(path);
        path = "/";
    }
    // 如果是多个函数需要循环添加层
    for (let i = 0; i < handlers.length; i++) {
        let layer = new Layer(path, handlers[i]);
        // 中间件不需要 route 属性
        layer.route = undefined;
        this.stack.push(layer);
    }
};

Router.prototype.handle = function (req, res, out) {
    console.log("请求到了");
    // 需要取出路由系统中 Router 存放的 layer 依次执行
    const { pathname } = url.parse(req.url);
    let idx = 0;
    let next = (err) => {
        // 遍历完后没有找到就直接走出路由系统
        if (idx >= this.stack.length) return out();
        let layer = this.stack[idx++];
        if (err) {
            console.log("统一对中间件跟路由错误处理");
            // 找错误处理中间件
            if (!layer.route) {
                // 如果是中间件自己处理
                layer.handle_error(err, req, res, next);
            } else {
                // 路由则跳过,继续携带错误向下执行
                next(err);
            }
        } else {
            // 需要判断 layer 上的 path 和当前请求路由是否一致,一致就执行 dispatch 方法
            if (layer.match(pathname)) {
                // 中间件没有方法可以匹配,不能是错误处理中间件
                if (!layer.route) {
                    if (layer.handler.length !== 4) {
                        layer.handle_request(req, res, next);
                    } else {
                        next();
                    }
                } else {
                    // 将遍历路由系统中下一层的方法传入
                    // 加速匹配,如果用户注册过这个类型的方法在去执行
                    if (layer.route.methods[req.method.toLowerCase()]) {
                        layer.handle_request(req, res, next);
                    } else {
                        next();
                    }
                }
            } else {
                next();
            }
        }
    };
    next();
};

module.exports = Router;

layer.js

function Layer(path, handler) {
    this.path = path;
    this.handler = handler;
}

Layer.prototype.match = function (pathname) {
    if (this.path === pathname) {
        return true;
    }
    // 如果是中间件,进行中间件的匹配规则
    if (!this.route) {
        if (this.path == "/") {
            return true;
        }
        // /aaaa/b 需要 /aaaa/ 才能匹配上
        return pathname.startsWith(this.path + "/");
    }
    return false;
};
Layer.prototype.handle_error = function (err, req, res, next) {
    if (this.handler.length === 4) {
        // 调用错误处理中间件
        return this.handler(err, req, res, next);
    }
    next(err); // 普通的中间件
};
Layer.prototype.handle_request = function (req, res, next) {
    this.handler(req, res, next);
};
module.exports = Layer;

route.js

const Layer = require("./layer");
const methods = require("methods");

function Route() {
    this.stack = [];
    // 用来描述内部存过哪些方法
    this.methods = {};
}

Route.prototype.dispatch = function (req, res, out) {
    // 稍后调用此方法时,回去栈中拿出对应的 handler 依次执行
    let idx = 0;
    console.log("this.stack----->", this.stack);
    let next = (err) => {
        // 如果内部迭代的时候出现错误,直接到外层的 stack 中
        err && out(err);
        // 遍历完后没有找到就直接走出路由系统
        if (idx >= this.stack.length) return out();
        let layer = this.stack[idx++];
        console.log("dispatch----->", layer.method);
        if (layer.method === req.method.toLowerCase()) {
            layer.handle_request(req, res, next);
        } else {
            next();
        }
    };
    next();
};
methods.forEach((method) => {
    Route.prototype[method] = function (handlers) {
        console.log("handlers----->", handlers);
        handlers.forEach((handler) => {
            // 这里的路径没有意义
            let layer = new Layer("/", handler);
            layer.method = method;
            // 做个映射表
            this.methods[method] = true;
            this.stack.push(layer);
        });
    };
});

module.exports = Route;

测试demo

const express = require("./kaimo-express");
const app = express();

app.use("/", (req, res, next) => {
    console.log("中间件1");
    next();
    // next("中间件1出错了");
});

app.use("/", (req, res, next) => {
    console.log("中间件2");
    // next();
    next("中间件2出错了");
});

app.use("/", (req, res, next) => {
    console.log("中间件3");
    next();
    // next("中间件3出错了");
});

app.get(
    "/",
    (req, res, next) => {
        console.log("路由1");
        next();
    },
    (req, res, next) => {
        res.end("出错了 *****");
    }
);

// 错误处理中间价
app.use((err, req, res, next) => {
    console.log("错误处理中间价----->", err);
    res.end(err);
});

app.listen(3000, () => {
    console.log(`server start 3000`);
    console.log(`在线访问地址:http://localhost:3000/`);
});

93 # 实现 express 错误处理中间件,Node / Node 框架,前端工程架构,express,中间件文章来源地址https://www.toymoban.com/news/detail-730397.html

到了这里,关于93 # 实现 express 错误处理中间件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • express中间件当做前端服务器的安全漏洞处理

    使用express当做node服务器时,发现安全漏洞,记录处理步骤: PS:以下安全内容处理,需要使用到redis进行会话存储、请求计数、请求唯一限制等。为尽量确保开发环境与部署环境一致,请开发环境安装并启动Redis服务。 ** 此文档只是说明记录关键步骤。具体实现代码可参照附

    2024年03月27日
    浏览(51)
  • Express中间件

    客户端发起的任何请求,到达服务器之后,都会触发的中间件 多个局部生效的中间件   中间件必须在路由之前注册   应用中间件 路由中间件 错误级别中间件              错误级别中间件必须在所有路由之后 内置中间件 举例:express.json() 08.中间件-自定义中间件_哔哩

    2024年02月13日
    浏览(44)
  • express框架中间件

    说明:Express框架中间件是指在处理HTTP请求前或后对请求和响应进行处理的函数。具体而言,中间件可以: 执行一些公共的逻辑,比如身份验证、日志记录、错误处理等。 修改请求和响应,比如缓存、压缩等。 控制请求流,比如路由控制、URL重定向等。 Express中间件可以是一

    2024年02月13日
    浏览(37)
  • 初识express/路由/中间件

                                     ​​​​​​​        

    2024年02月11日
    浏览(65)
  • 【Express】文件上传管理 multer 中间件

    Multer是Node.js中用于处理文件上传的中间件。它可以帮助你处理文件上传的相关逻辑,如接收和保存上传的文件、限制文件大小、设置文件类型限制等。只能用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件。 下面是使用Multer中间件的基本步骤: 安装multer:在命

    2024年02月07日
    浏览(44)
  • 编写中间件以用于 Express 应用程序

    中间件 函数能够访问请求对象 ( req )、响应对象 ( res ) 以及应用程序的请求/响应循环中的下一个中间件函数。下一个中间件函数通常由名为  next  的变量来表示。 中间件函数可以执行以下任务: 执行任何代码。 对请求和响应对象进行更改。 结束请求/响应循环。 调用堆栈

    2024年02月10日
    浏览(41)
  • node中间件-koa框架

    安装 npm i koa koa导出的是一个类,必须用 new 进行创建 koa也是通过注册中间件来完成请求操作的 koa注册的中间件提供了两个参数: ctx:上下文(Context)对象; koa并没有像express一样,将req和res分开,而是将它们作为ctx的属性; ctx代表一次请求的上下文对象; ctx.reque

    2024年02月16日
    浏览(56)
  • 第九篇:node静态文件服务(中间件)

     🎬 江城开朗的豌豆 :个人主页  🔥 个人专栏  :《 VUE 》 《 javaScript 》  📝  个人网站  :《 江城开朗的豌豆🫛 》  ⛺️ 生活的理想,就是为了理想的生活 ! 当今互联网时代,Node.js 成为了最受欢迎的服务器端开发平台之一。作为一名小白,学习 Node.js 可能会让你感

    2024年02月20日
    浏览(43)
  • cool Node后端 中实现中间件的书写

    1.需求 在node后端中,想实现一个专门鉴权的文件配置,可以这样来解释 就是 有些接口需要token调用接口,有些接口不需要使用token 调用  这期来详细说明一下      什么是中间件中间件顾名思义是指在请求和响应中间,进行请求数据的拦截处理,数据校验,并且进行逻辑处理

    2024年02月20日
    浏览(44)
  • Node.js 使用 cors 中间件解决跨域问题

    cors 是 Express 的一个第三方中间件。通过安装和配置 cors 中间件,可以很方便地解决跨域问题。 CORS (Cross-Origin Resource Sharing,跨域资源共享)由一系列 HTTP 响应头 组成, 这些 HTTP 响应头决定浏览器是否阻止前端 JS 代码跨域获取资源 。 浏览器的 同源安全策略 默认会阻止网

    2024年01月20日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包