Node.js is a Javascript runtime built on Chrome's V8 Javascipt engine(基于chrome V8引擎浏览器构建的运行环境

简单来说,Node.js 就是运行在服务端的Javascript

Node.js是一个事件驱动I/O服务端Javascript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好

Node中有一个非常重要的概念:中间件

中间件是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务、功能,衔接网络上应用系统中的各个部分或不同的应用,能够达到资源共享、功能共享的目的。

在nodeJs中,中间件函数是可以访问请求对象(req)和 响应对象(res)以及应用程序的请求、响应周期中的下一个中间件函数的函数(下一个中间件函数通常由名为变量的next表示)

中间件可能执行的任务:

  • 执行任何代码
  • 更改请求和响应对象
  • 结束请求-响应周期
  • 调用堆栈中的下一个中间件函数

举个例子,我们在http请求中往往设计到很多动作,比如域名解析、IP地址解析、请求体解析cookie信息处理、日志记录等等,对开发工作者来说,我们更多的是关注业务的开发,而不是每个细节的流程处理,于是就有了中间件的概念,中间件来简化和封装这里基本逻辑的细节处理。这样就大大提高了开发者的效率

中间件本质上就是一层一层的过滤器,就像我们在网上买菜一样,叮咚买菜流程:

  1. 下单购买:在叮咚买菜的网站或移动应用程序上选择所需的商品,放入购物车中,然后选择收货地址和配送时间,并完成订单支付。
  2. 商家备货:叮咚买菜会与当地的生鲜供应商和超市合作,让其为客户的订单备货。商家将挑选出新鲜的食材,并按照订单要求进行包装。
  3. 配送员接单:在订单支付成功后,叮咚买菜的配送员将接到该订单,并在指定的配送时间和地址前往商家门店。
  4. 配送员取货:配送员到达商家门店后,会凭借订单信息取货。商家将会把订单打包好的商品交给配送员。
  5. 配送员配送:配送员根据订单中指定的地址,将商品送到客户所指定的地址,并将商品交到客户手中。在这个过程中,叮咚买菜的配送员将与客户保持沟通,确保订单按时到达。
  6. 确认收货:客户收到商品后,需要对商品进行验收,确保订单中的商品完好无损。如果商品有任何质量问题,客户可以联系叮咚买菜客服进行退换货处理

对我们买菜者来说,我们只需要关注我们买了什么,什么时候可以拿到货,不需要关注,怎么备货、那个配送员接单、送货等,这中间的流程就可以交给第三方来处理,这第三方就相当于是一个中间件,nodejs中的中间件同理,开发者只关心请求数据时需要什么条件和能拿到返回的数据,而这请求的过程就可以经过一层一层的封装过滤,如下图所示:

什么中间件用go语言实现 中间件 js_javascript

 node中间件核心原理实现:

由上文介绍可知中间件是从http请求开始到响应结束过程中的处理逻辑,通常需要对请求和响应进行处理. 我们在实现node中间件模式时还需要考虑的一个问题就是多中间件共存的问题, 我们要思考如何将多个中间件的执行自动化, 不然在请求到响应的过程中只会执行最开始的中间件, 所以我们基本的中间件形式如下:

const middleware = (req, res, next) => {
  // 请求处理逻辑
  next()
}

接下来我们先写个简单的案例来看看中间件是如何实现的:

// 定义几个中间间函数
const m1 = (req, res, next) => {
  console.log('m1 run')
  next()
}

const m2 = (req, res, next) => {
  console.log('m2 run')
  next()
}

const m3 = (req, res, next) => {
  console.log('m3 run')
  next()
}

// 中间件集合
const middlewares = [m1, m2, m3]

function useApp (req, res) {
  const next = () => {
    // 获取第一个中间件
    const middleware = middlewares.shift()
    if (middleware) {
      middleware(req, res, next)
    }
  }
  next()
}

// 第一次请求流进入
useApp()

打印结果为:

m1 run m2 run m3 run

由结果可看出,next的作用就是在每一次任务执行完了之后,自动会执行下一个任务

 在我们实际来发中我们请求的数据,往往更多色时候还要考虑异步的问题,所以往往我们会通过promise来进行封装然后将异步的任务变成同步的任务

const m1 = async (req, res, next) => {
    // something...
    let result = await next();
  }

  const m2 = async (req, res, next) => {
    // something...
    let result = await next();
  }
  const m3 = async (req, res, next) => {
    // something...
    let result = await next();
    return result;
  }

const middlewares = [m1, m2, m3];

function useApp (req, res) {
    const next = () => {
      const middleware = middlewares.shift()
      if (middleware) {
        return Promise.resolve(middleware(req, res, next))
      }else {
        return Promise.resolve("end")
      }
    }
    next()
}
// 启动中间件
useApp()