前言
在使用 Hapi.js 开发 web 应用时,我们常常需要借助中间件来完成一些特定的任务,比如身份认证、日志记录、错误处理等等。本文将介绍 Hapi.js 中间件的原理及实践,重点讲解如何封装中间件来避免重复编写 bug。
Hapi.js 中间件是什么
中间件(Middleware)是 Hapi.js 的一种插件机制,类似于 Express 中的中间件。中间件是一段可插拔的代码,可以在请求被处理前、处理过程中或者处理后对请求进行拦截、修改、增强等操作。在 Hapi.js 中,中间件可以被添加到路由上,也可以被添加到服务器实例上。
Hapi.js 中间件的分类
Hapi.js 中间件可以分为两类:
应用级中间件
应用级中间件是添加到路由上的中间件,只能针对指定的路由生效。应用级中间件可以通过 server.route()
方法来添加,也可以通过路由选项中的 pre
或者 post
字段来添加。
示例代码
// javascriptcn.com 代码示例 const Hapi = require('hapi'); const server = new Hapi.Server(); server.connection({ host: 'localhost', port: 8000, }); server.route({ method: 'GET', path: '/hello', handler: (request, reply) => { reply('Hello, World!'); }, config: { pre: [{ assign: 'logger', method: (request, reply) => { console.log(`[${new Date().toISOString()}] ${request.method.toUpperCase()} ${request.path}`); reply.continue(); } }] } });
在上面的代码中,我们添加了一个应用级中间件,用来记录请求日志。该中间件的主体逻辑是将请求方法、请求路径和当前时间输出到控制台。中间件的添加方式是通过设置路由选项的 pre
字段来实现的。
插件级中间件
插件级中间件是添加到服务器实例上的中间件,可以对所有路由生效。插件级中间件可以通过 server.ext()
方法来添加。
示例代码
// javascriptcn.com 代码示例 const Hapi = require('hapi'); const server = new Hapi.Server(); server.connection({ host: 'localhost', port: 8000, }); server.ext('onPreHandler', (request, reply) => { console.log(`[${new Date().toISOString()}] ${request.method.toUpperCase()} ${request.path}`); reply.continue(); }); server.route({ method: 'GET', path: '/hello', handler: (request, reply) => { reply('Hello, World!'); } });
在上面的代码中,我们添加了一个插件级中间件,用来记录请求日志。该中间件的主体逻辑和应用级中间件是相同的,唯一的区别是添加方式。中间件的添加方式是通过 server.ext()
方法实现的。
中间件的执行顺序
在 Hapi.js 中,每个请求都会经过一系列中间件的处理,我们需要了解这些中间件的执行顺序。
Hapi.js 中间件的执行顺序可分为三个阶段:
- 应用级前置中间件(app pre-handler)
- 路由级前置中间件(route pre-handler)
- 路由处理函数(route handler)
- 路由级后置中间件(route post-handler)
- 应用级后置中间件(app post-handler)
应用级前置中间件是添加到服务器实例上的中间件,是所有中间件中最先执行的;应用级后置中间件也是添加到服务器实例上的中间件,是所有中间件中最后执行的。路由级中间件分为前置和后置两种,在路由级中间件和路由处理函数之间的执行顺序是由路由选项中 pre
字段和 handler
字段的定义顺序决定的。
封装中间件
当我们需要在多个路由或者多个项目中使用同一个中间件时,我们可以将其封装为一个单独的模块,避免重复编写代码。下面我们以错误处理中间件为例,来介绍如何封装中间件。
示例代码
/** * 错误处理中间件 */ module.exports = (error, request, reply) => { console.error(error); // 输出错误信息到控制台 reply(`Oops! Something went wrong. Error message: ${error.message}`); // 返回错误信息 };
在上面的代码中,我们将一个错误处理中间件封装成了一个可复用的模块。当请求出现错误时,该中间件将输出错误信息到控制台,并返回一个错误信息给客户端。
我们可以将该中间件添加到多个路由中,如下所示:
// javascriptcn.com 代码示例 const errorMiddleware = require('./middlewares/error'); server.route({ method: 'GET', path: '/hello', handler: (request, reply) => { try { throw new Error('Test error'); } catch (error) { errorMiddleware(error, request, reply); } } }); server.route({ method: 'GET', path: '/foo', handler: (request, reply) => { try { // Do something } catch (error) { errorMiddleware(error, request, reply); } } });
可以看到,通过封装中间件,我们可以避免重复编写相同的错误处理逻辑,并且更易于维护。
总结
Hapi.js 中间件是一种非常强大的插件机制,可以通过添加中间件来实现各种特定的功能。在编写中间件时,我们需要了解中间件的分类和执行顺序,以及如何封装中间件避免重复编写代码。希望本文能对你了解 Hapi.js 中间件有所帮助。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6534f7dc7d4982a6ebab157b