Hapi 框架中的 Pre Handler 函数调用顺序问题及解决方法

阅读时长 9 分钟读完

Hapi 是一个流行的 Node.js 框架,它提供一系列的插件和基础设施,使得开发者可以更加容易地构建快速、安全、可扩展的 Web 应用程序。在 Hapi 中,Pre Handler 函数是一个非常有用的功能,它可以在处理请求之前执行一些操作以准备数据或者检查权限等等。然而,Pre Handler 函数的调用顺序问题在实践中经常会导致很多困惑和错误。本文将详细探讨这个问题,并提供一些解决方法和最佳实践。

Pre Handler 函数的基本用法

Hapi 中,Pre Handler 函数是用来进行请求前处理的函数,可以用来完成以下操作:

  • 从请求中提取数据并进行验证
  • 从数据库中获取数据
  • 设置请求的上下文信息
  • 根据某些条件决定是否允许请求继续执行

Pre Handler 函数可以返回一个结果,这个结果会被传递给后续的处理函数,比如路由处理函数。可以将多个 Pre Handler 函数串联起来使用,它们的执行顺序可以是串行的或者并行的。

以下是一个非常简单的 Pre Handler 函数的例子:

这个函数从请求中提取 data 参数,并将其保存到 formData 属性中。如果 data 参数不存在,则返回一个错误响应并中断请求。

Pre Handler 函数的执行顺序问题

Hapi 中,可以将多个 Pre Handler 函数串联起来使用,如下所示:

-- -------------------- ---- -------
--------------
  ------- ------
  ----- ----
  -------- --------- -- -- -
    ------ ------- ---------------------------
  --
  -------- -
    ---- -
      ------------
      ------------
      -----------
    -
  -
---

在这个例子中,有三个 Pre Handler 函数被注册,它们的执行顺序是 preHandler1 -> preHandler2 -> preHandler3。这种执行顺序被称为“串行”。

在实践中,我们可能会需要对多个 Pre Handler 函数进行排序,以确保它们按照正确的顺序执行。例如,假设我们有以下两个 Pre Handler 函数:

如果我们希望在 preHandlerA 函数执行之前,先执行 preHandlerB 函数,我们该如何实现呢?

-- -------------------- ---- -------
--------------
  ------- ------
  ----- ----
  -------- --------- -- -- -
    ------ ------- --------
  --
  -------- -
    ---- -
      - ------- ------------ -------- - ------- ------------- - --
      -----------
    -
  -
---

这样设置之后,就可以按照预期的顺序执行这两个函数了。

Pre Handler 函数的调用顺序冲突

然而,即使我们对 Pre Handler 函数按照顺序进行了设置,仍然可能会遇到一些错误和冲突。例如,假设我们有以下三个函数:

-- -------------------- ---- -------
----- ----------- - ----- --------- -- -- -
  ---------------------------
  ----- --- --------------- -- ------------------- -------
  ------------------------ -------
--

----- ----------- - ----- --------- -- -- -
  ---------------------------
  ----- --- --------------- -- ------------------- ------
  ------------------------ -------
--

----- ----------- - --------- -- -- -
  ---------------------------
--

在这个例子中,preHandler1preHandler2 都是异步函数,它们分别需要 1 秒和半秒的时间来完成。如果我们按照如下的顺序注册这些函数:

-- -------------------- ---- -------
--------------
  ------- ------
  ----- ----
  -------- --------- -- -- -
    ------ ------- --------
  --
  -------- -
    ---- -
      ------------
      ------------
      -----------
    -
  -
---

则得到的结果很可能与预期不同。我们的预期结果是:

但是实际上输出的结果可能是:

这是因为 Hapi 并没有对异步 Pre Handler 函数的执行顺序进行排序,而是按照它们的注册顺序进行调用。这就导致了它们的执行顺序可能会发生冲突。

Pre Handler 函数的解决方法

为了解决上述问题,我们可以使用 Hapi 提供的一些方法来调整 Pre Handler 函数的执行顺序。下面是一些常用的方法:

before 和 after

beforeafter 选项可以将一个 Pre Handler 函数放置在另一个函数的前面或者后面。例如,如果我们希望 preHandler1preHandler2 之后执行,可以按照如下的方式注册:

-- -------------------- ---- -------
--------------
  ------- ------
  ----- ----
  -------- --------- -- -- -
    ------ ------- --------
  --
  -------- -
    ---- -
      ------------
      ------------
      -----------
    -
  -
---

这样可以确保 preHandler2 先于 preHandler1 执行。

parallel 和 serial

parallelserial 选项可以指定多个 Pre Handler 函数的执行方式。parallel 类似于异步并发执行,即同时执行多个函数,而serial 则按照顺序逐个执行函数。例如,我们可以按照如下的方式注册 Pre Handler 函数:

-- -------------------- ---- -------
--------------
  ------- ------
  ----- ----
  -------- --------- -- -- -
    ------ ------- --------
  --
  -------- -
    ---- -
      - ------- ------------ -------- - ------- ---- - --
      - ------- ------------ -------- - --------- ---- - --
      -----------
    -
  -
---

这样会按照以下顺序执行这三个函数:

  1. 执行 preHandler2
  2. 执行 preHandler3
  3. 执行 preHandler1

分组

如果您需要将 Pre Handler 函数分组,并且需要在不同的路由中复用这些函数,可以使用 pre.app 选项。例如,我们可以按照如下的方式分组:

-- -------------------- ---- -------
----- ------ - -
  ----- ---------
  ------------ -
    ------------
    -----------
  -
--

----- ------ - -
  ----- ---------
  ------------ -
    -----------
  -
--

-- -----
--------------
  ------- ------
  ----- ----
  -------- --------- -- -- -
    ------ ------- --------
  --
  -------- -
    ---- -
      - ------- ------------------ --
      - ------- ------------------ -
    --
    ---- ------
  -
---

-- -----
--------------
  ------- ------
  ----- --------
  -------- --------- -- -- -
    ------ ------- -------
  --
  -------- -
    ---- -
      - ------- ------------------ -
    --
    ---- ------
  -
---

这样,我们就可以在不同的路由中使用不同的 Pre Handler 函数组,而且它们之间不会互相干扰。

总结

HapiPre Handler 函数是一个非常有用的工具,可以用于在处理请求之前进行一些操作。然而,在实践中, Pre Handler 函数的执行顺序问题可能会导致很多困惑和错误。为了解决这个问题,我们可以使用各种方法和选项,如 beforeafterparallelserial 以及 pre.app 等等。通过合理设置 Pre Handler 函数的执行顺序,可以让我们的应用程序更加稳定、更易于维护,提高开发效率。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/651e6f7195b1f8cacd616252

纠错
反馈