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信息处理、日志记录等等,对开发工作者来说,我们更多的是关注业务的开发,而不是每个细节的流程处理,于是就有了中间件的概念,中间件来简化和封装这里基本逻辑的细节处理。这样就大大提高了开发者的效率
中间件本质上就是一层一层的过滤器,就像我们在网上买菜一样,叮咚买菜流程:
- 下单购买:在叮咚买菜的网站或移动应用程序上选择所需的商品,放入购物车中,然后选择收货地址和配送时间,并完成订单支付。
- 商家备货:叮咚买菜会与当地的生鲜供应商和超市合作,让其为客户的订单备货。商家将挑选出新鲜的食材,并按照订单要求进行包装。
- 配送员接单:在订单支付成功后,叮咚买菜的配送员将接到该订单,并在指定的配送时间和地址前往商家门店。
- 配送员取货:配送员到达商家门店后,会凭借订单信息取货。商家将会把订单打包好的商品交给配送员。
- 配送员配送:配送员根据订单中指定的地址,将商品送到客户所指定的地址,并将商品交到客户手中。在这个过程中,叮咚买菜的配送员将与客户保持沟通,确保订单按时到达。
- 确认收货:客户收到商品后,需要对商品进行验收,确保订单中的商品完好无损。如果商品有任何质量问题,客户可以联系叮咚买菜客服进行退换货处理
对我们买菜者来说,我们只需要关注我们买了什么,什么时候可以拿到货,不需要关注,怎么备货、那个配送员接单、送货等,这中间的流程就可以交给第三方来处理,这第三方就相当于是一个中间件,nodejs中的中间件同理,开发者只关心请求数据时需要什么条件和能拿到返回的数据,而这请求的过程就可以经过一层一层的封装过滤,如下图所示:
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()