Hapi
是一个流行的 Node.js 框架,它提供一系列的插件和基础设施,使得开发者可以更加容易地构建快速、安全、可扩展的 Web 应用程序。在 Hapi
中,Pre Handler
函数是一个非常有用的功能,它可以在处理请求之前执行一些操作以准备数据或者检查权限等等。然而,Pre Handler
函数的调用顺序问题在实践中经常会导致很多困惑和错误。本文将详细探讨这个问题,并提供一些解决方法和最佳实践。
Pre Handler 函数的基本用法
在 Hapi
中,Pre Handler
函数是用来进行请求前处理的函数,可以用来完成以下操作:
- 从请求中提取数据并进行验证
- 从数据库中获取数据
- 设置请求的上下文信息
- 根据某些条件决定是否允许请求继续执行
Pre Handler
函数可以返回一个结果,这个结果会被传递给后续的处理函数,比如路由处理函数。可以将多个 Pre Handler
函数串联起来使用,它们的执行顺序可以是串行的或者并行的。
以下是一个非常简单的 Pre Handler
函数的例子:
const preHandler = (request, h) => { const data = request.query.data; if (!data) { return h.response('Please provide valid data').code(400); } request.formData = { data }; };
这个函数从请求中提取 data
参数,并将其保存到 formData
属性中。如果 data
参数不存在,则返回一个错误响应并中断请求。
Pre Handler 函数的执行顺序问题
在 Hapi
中,可以将多个 Pre Handler
函数串联起来使用,如下所示:
-- -------------------- ---- ------- -------------- ------- ------ ----- ---- -------- --------- -- -- - ------ ------- --------------------------- -- -------- - ---- - ------------ ------------ ----------- - - ---
在这个例子中,有三个 Pre Handler
函数被注册,它们的执行顺序是 preHandler1
-> preHandler2
-> preHandler3
。这种执行顺序被称为“串行”。
在实践中,我们可能会需要对多个 Pre Handler
函数进行排序,以确保它们按照正确的顺序执行。例如,假设我们有以下两个 Pre Handler
函数:
const preHandlerA = (request, h) => { console.log('preHandlerA'); }; const preHandlerB = (request, h) => { console.log('preHandlerB'); };
如果我们希望在 preHandlerA
函数执行之前,先执行 preHandlerB
函数,我们该如何实现呢?
-- -------------------- ---- ------- -------------- ------- ------ ----- ---- -------- --------- -- -- - ------ ------- -------- -- -------- - ---- - - ------- ------------ -------- - ------- ------------- - -- ----------- - - ---
这样设置之后,就可以按照预期的顺序执行这两个函数了。
Pre Handler 函数的调用顺序冲突
然而,即使我们对 Pre Handler
函数按照顺序进行了设置,仍然可能会遇到一些错误和冲突。例如,假设我们有以下三个函数:
-- -------------------- ---- ------- ----- ----------- - ----- --------- -- -- - --------------------------- ----- --- --------------- -- ------------------- ------- ------------------------ ------- -- ----- ----------- - ----- --------- -- -- - --------------------------- ----- --- --------------- -- ------------------- ------ ------------------------ ------- -- ----- ----------- - --------- -- -- - --------------------------- --
在这个例子中,preHandler1
和 preHandler2
都是异步函数,它们分别需要 1 秒和半秒的时间来完成。如果我们按照如下的顺序注册这些函数:
-- -------------------- ---- ------- -------------- ------- ------ ----- ---- -------- --------- -- -- - ------ ------- -------- -- -------- - ---- - ------------ ------------ ----------- - - ---
则得到的结果很可能与预期不同。我们的预期结果是:
preHandler2 preHandler2 done preHandler3 preHandler1 preHandler1 done
但是实际上输出的结果可能是:
preHandler2 preHandler3 preHandler1 preHandler2 done preHandler1 done
这是因为 Hapi
并没有对异步 Pre Handler
函数的执行顺序进行排序,而是按照它们的注册顺序进行调用。这就导致了它们的执行顺序可能会发生冲突。
Pre Handler 函数的解决方法
为了解决上述问题,我们可以使用 Hapi
提供的一些方法来调整 Pre Handler
函数的执行顺序。下面是一些常用的方法:
before 和 after
before
和 after
选项可以将一个 Pre Handler
函数放置在另一个函数的前面或者后面。例如,如果我们希望 preHandler1
在 preHandler2
之后执行,可以按照如下的方式注册:
-- -------------------- ---- ------- -------------- ------- ------ ----- ---- -------- --------- -- -- - ------ ------- -------- -- -------- - ---- - ------------ ------------ ----------- - - ---
这样可以确保 preHandler2
先于 preHandler1
执行。
parallel 和 serial
parallel
和 serial
选项可以指定多个 Pre Handler
函数的执行方式。parallel
类似于异步并发执行,即同时执行多个函数,而serial
则按照顺序逐个执行函数。例如,我们可以按照如下的方式注册 Pre Handler
函数:
-- -------------------- ---- ------- -------------- ------- ------ ----- ---- -------- --------- -- -- - ------ ------- -------- -- -------- - ---- - - ------- ------------ -------- - ------- ---- - -- - ------- ------------ -------- - --------- ---- - -- ----------- - - ---
这样会按照以下顺序执行这三个函数:
- 执行
preHandler2
- 执行
preHandler3
- 执行
preHandler1
分组
如果您需要将 Pre Handler
函数分组,并且需要在不同的路由中复用这些函数,可以使用 pre.app
选项。例如,我们可以按照如下的方式分组:
-- -------------------- ---- ------- ----- ------ - - ----- --------- ------------ - ------------ ----------- - -- ----- ------ - - ----- --------- ------------ - ----------- - -- -- ----- -------------- ------- ------ ----- ---- -------- --------- -- -- - ------ ------- -------- -- -------- - ---- - - ------- ------------------ -- - ------- ------------------ - -- ---- ------ - --- -- ----- -------------- ------- ------ ----- -------- -------- --------- -- -- - ------ ------- ------- -- -------- - ---- - - ------- ------------------ - -- ---- ------ - ---
这样,我们就可以在不同的路由中使用不同的 Pre Handler
函数组,而且它们之间不会互相干扰。
总结
Hapi
的 Pre Handler
函数是一个非常有用的工具,可以用于在处理请求之前进行一些操作。然而,在实践中, Pre Handler
函数的执行顺序问题可能会导致很多困惑和错误。为了解决这个问题,我们可以使用各种方法和选项,如 before
、 after
、 parallel
、 serial
以及 pre.app
等等。通过合理设置 Pre Handler
函数的执行顺序,可以让我们的应用程序更加稳定、更易于维护,提高开发效率。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/651e6f7195b1f8cacd616252