返回顶部
首页 > 资讯 > 前端开发 > node.js >nodejs对express中next函数的一些理解
  • 536
分享到

nodejs对express中next函数的一些理解

函数nodejsexpress 2022-06-04 17:06:41 536人浏览 泡泡鱼
摘要

最近公司在使用node做前后端分离,采用的WEB框架是express,所以对express框架进行了深入的了解,前段时间写了篇关于express路由的文章,但是在那篇文章中貌似少了一个很重要的内容,就是ex

最近公司在使用node做前后端分离,采用的WEB框架是express,所以对express框架进行了深入的了解,前段时间写了篇关于express路由的文章,但是在那篇文章中貌似少了一个很重要的内容,就是express的next,所以今天单独来说说express的next。

关于next主要从三点来进行说明:

next的作用是什么? 我们应该在何时使用next? next的内部实现机制是什么?

Next的作用

我们在定义express中间件函数的时候都会将第三个参数定义为next,这个next就是我们今天的主角,next函数主要负责将控制权交给下一个中间件,如果当前中间件没有终结请求,并且next没有被调用,那么请求将被挂起,后边定义的中间件将得不到被执行的机会。

何时使用Next

从上边的描述我们已经知道,next函数主要是用来确保所有注册的中间件被一个接一个的执行,那么我们就应该在所有的中间件中调用next函数,但有一个特例,如果我们定义的中间件终结了本次请求,那就不应该再调用next函数,否则就可能会出问题,我们来看段代码


app.get('/a', function(req, res, next) {
  res.send('sucess');
  next();
});

// catch 404 and forward to error handler
app.use(function(req, res, next) {
 console.log(404);
 var err = new Error('Not Found');
 err.status = 404;
 next(err);
});

app.use(function(err, req, res, next) {
 res.status(err.status || 500);
 res.render('error', {
  message: err.message,
  error: {}
 });
});

发送请求"/a",控制台打印日志如下:


404
GET /a 500 6.837 ms - -
Error: Can't set headers after they are sent.
  at ServerResponse.OutGoingMessage.setHeader (_Http_outgoing.js:345:11)

为什么代码会抛异常呢,就是因为我们在res.send之后调用了next函数,虽然我们本次的请求已经被终止,但后边的404中间件依旧会被执行,而后边的中间件试图去向res的headers中添加属性值,所以就会抛出上边的异常。

读到这你可能会有个疑问,如果我不在res.send后边调用next函数,那后边定义的404中间件是不是永远都不会被执行到。现在我们删除res.send后边next函数调用,发送请求"/xxx",我们就会发现404中间件被执行了,(ㄒoㄒ),这不是和我们之前说的矛盾了吗,我们的自定义中间件没有调用next,但后边定义的中间件仍旧被执行了,这究竟是为什么呢。看来只能求助源码了~~~

Next的内部机制


function next(err) {
  ... //此处源码省略
  // find next matching layer
  var layer;
  var match;
  var route;

  while (match !== true && idx < stack.length) {
   layer = stack[idx++];
   match = matchLayer(layer, path);
   route = layer.route;

   if (typeof match !== 'boolean') {
    // hold on to layerError
    layerError = layerError || match;
   }

   if (match !== true) {
    continue;
   }
   ... //此处源码省略
  }
 ... //此处源码省略
  // this should be done for the layer
  if (err) {
    layer.handle_error(err, req, res, next);
  } else {
   layer.handle_request(req, res, next);
  }
 }

上边就是express中next的源码,为了更容易说明问题,对代码进行了删减。从上边的源码可以发现,next函数内部有个while循环,每次循环都会从stack中拿出一个layer,这个layer中包含了路由和中间件信息,然后就会用layer和请求的path就行匹配,如果匹配成功就会执行layer.handle_request,调用中间件函数。但如果匹配失败,就会循环下一个layer(即中间件)。

现在我们就能解释上边提出的问题了,为什么我们的自定义中间件中没调用next函数,但后边的404中间件仍旧会被执行到,因为我们请求的"/xxx"匹配不到我们注册的"/a"路由中间件,所以while循环会继续往下执行,匹配404中间件成功,所以会执行404中间件。

注意:app.use注册的中间件,如果path参数为空,则默认为"/",而path为"/"的中间件默认匹配所有的请求。

有一点需要特别指出,其实我们在定义路由中间件的时候函数的第三个参数next和我们定义非路由中间件的函数的第三个参数next不是同一个next,我们在上边看到的是非路由中间件的next,而路由中间件的next函数是这样的


function next(err) {
  if (err && err === 'route') {
   return done();
  }

  var layer = stack[idx++];
  if (!layer) {
   return done(err);
  }

  if (layer.method && layer.method !== method) {
   return next(err);
  }

  if (err) {
   layer.handle_error(err, req, res, next);
  } else {
   layer.handle_request(req, res, next);
  }
 }

这个next比上边的那个next要简单很多,它负责同一个路由的多个中间件的控制权的传递,并且它会接收一个参数"route",如果调用next(“route”),则会跳过当前路由的其它中间件,直接将控制权交给下一个路由。

最后有必要再说一说next(err),next(err)是如何将控制权传递到错误处理中间件的,从前边的代码我们知道,当调用next(err)是,express内部会调用layer.handle_error,那我们来看看它的源码


Layer.prototype.handle_error = function handle_error(error, req, res, next) {
 var fn = this.handle;

 if (fn.length !== 4) {
  // not a standard error handler
  return next(error);
 }

 try {
  fn(error, req, res, next);
 } catch (err) {
  next(err);
 }
};

代码中的fn就是中间件函数,express会对fn的参数个数进行判断,如果参数个数不等于4则认为不是错误处理中间件,则继续调用next(err),这样就会进入到下一个中间件函数,继续进行参数个数判断,如此方式一直到某个中间件函数的参数个数是4,就认为找到了错误处理中间件,然后执行此中间件函数。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: nodejs对express中next函数的一些理解

本文链接: https://lsjlt.com/news/12415.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • nodejs对express中next函数的一些理解
    最近公司在使用node做前后端分离,采用的web框架是express,所以对express框架进行了深入的了解,前段时间写了篇关于express路由的文章,但是在那篇文章中貌似少了一个很重要的内容,就是ex...
    99+
    2022-06-04
    函数 nodejs express
  • 深入理解nodejs中Express的中间件
    Express是一个基于Node.js平台的web应用开发框架,在Node.js基础之上扩展了web应用开发所需要的基础功能,从而使得我们开发Web应用更加方便、更加快捷。 举一个例子: 用node.js实...
    99+
    2022-06-04
    中间件 nodejs Express
  • nodejs中的时间函数有哪些
    小编给大家分享一下nodejs中的时间函数有哪些,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧! nodejs中的时间函数:1、moment();2、format...
    99+
    2024-04-02
  • 对JDBC的一些理解
    JDBC是一种执行SQL语句的java api,是java访问数据库的桥梁,它可以为多种关系型数据库提供统一的访问接口。   实现JDBC(此为连接oracle)的六个步骤:&...
    99+
    2024-04-02
  • Oracle中的一些函数
    一、比较大小函数 sign 函数语法:sign(n) 函数说明:取数字n的符号,大于0返回1;小于0返回-1;等于0返回0 示例:1、select sign( 2 ),sign(- 2 ),sig...
    99+
    2024-04-02
  • 理解JavaScript中window对象的一些用途
    目录前言浏览器对象模型浏览器环境深入全局变量对话框谨慎使用原生对话框浏览器信息Navigator对象URL浏览器历史控制窗口烦人的弹框屏幕信息更适用于移动平台谨慎使用文档对象docu...
    99+
    2024-04-02
  • JavaScript原型链中函数和对象的理解
    目录__ proto__prototype.__ proto__理解__ proto__ 最近在看高程4,原型链肯定是绕不过的,本瓜之前一直认为,只要记住这句话就可以了: 一个对象的...
    99+
    2024-04-02
  • C#中的一些延时函数
    C#一些延时函数 sleep延时方法 System.Threading.Thread.Sleep(1000); //毫秒 实现的是非独占性延时函数,延时过时中界面仍可响应消息: pu...
    99+
    2024-04-02
  • python中一些有用的函数------
    strip() 函数 用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 str2 = " Runoob " # 去除首尾空格 print (str2.strip()) 结果 Runoob isinsta...
    99+
    2023-01-31
    函数 有用 python
  • 一文读懂C++中的函数对象
    这篇文章给大家介绍一文读懂C++中的函数对象,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。如果一个类将()运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象。函数对象是一个对象,但是使用的形式看起来...
    99+
    2023-06-06
  • PHP 函数库中有哪些面向对象的函数?
    php 提供了丰富的 oop 函数库,可简化开发工作:常用 oop 函数:splfixedarray(固定长度数组)、splobjectstorage(存储对象)、splpriority...
    99+
    2024-04-27
    php 面向对象
  • 【整理总结】一些php中常用的内置函数
    作为一个广泛使用的编程语言,PHP有许多内置函数可供使用。在编码过程中,掌握这些函数可以使开发人员更快速、高效地编写代码。本文将探讨 PHP 中常用的一些函数。一、字符串处理函数strlen(string $string):获取字符串长度该...
    99+
    2023-05-14
  • php中一些常见的数组函数有哪些
    小编给大家分享一下php中一些常见的数组函数有哪些,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!php有什么特点1、执行速度快。2、具有很好的开放性和可扩展性。3、PHP支持多种主流与非主流的数据库。4、面向对象编程:PH...
    99+
    2023-06-14
  • Python中的配对函数zip()解读
    目录Python配对函数zip()1、zip将列表、元组或其他序列的元素进行配对2、zip的常用场景为同时遍历多个序列3、对于已“配对”的序列说说zip函数的...
    99+
    2024-04-02
  • 一文带你理解JavaScript中的函数式编程
    目录分析理解纯函数相同的输入参数,总会有相同的输出在执行过程中不会产生语义上可观察的 副作用纯函数 的作用不确定性的危害确定性的好处如何对待副作用总结我理解的 函数式编程 是一种 编...
    99+
    2023-02-20
    JavaScript函数式编程 JS函数式编程 JavaScript编程
  • MyBatis中多对一和一对多数据的处理方法
    目录多对一的处理1、数据库设计2、搭建测试环境3、按查询嵌套处理4 、按结果嵌套处理一对多的处理1、实体类编写2、按结果嵌套处理3、按查询嵌套处理4、小结多对一的处理 多对一的理解:...
    99+
    2023-01-03
    MyBatis多对一 MyBatis一对多处理
  • golang中的defer函数理解
    目录golang的defer什么是defer理解deferdefer什么时间执行(defer、 return、返回值 三者的执行顺序)defer输出的值,就是定义时的值。而不是def...
    99+
    2024-04-02
  • Python编程中对super函数的正确理解和用法解析
    当在子类需要调用父类的方法时,在python2.2之前,直接用类名调用类的方法,即非绑定的类方法,并把自身对象self作参数传进去。 class A(object): def say(self):...
    99+
    2022-06-04
    中对 函数 正确理解
  • 面向对象编程中的 C++ 函数声明:理解成员函数的特殊性
    c++++ 中成员函数的特殊声明约定包括:显式指定所属类名,表明函数属于哪个类。隐式 this 指针,指向调用该函数的对象,允许访问对象数据成员和方法。 面向对象编程中的 C++ 函数...
    99+
    2024-05-04
    c++ 面向对象编程
  • 浅谈对Python变量的一些认识理解
    一、Python变量 在大多数语言中,为一个值起一个名字时,把这种行为称为“给变量赋值”或“把值存储在变量中”。不过,Python与许多其它计算机语言的有所不同,它并不是把值存储在变...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作