应用程序实例 App Instance

App实例是h3服务器的核心。

h3 服务器的核心是 app 实例。它是处理传入请求的服务器的核心。您可以使用 app 实例来注册事件处理程序。

初始化应用程序

您可以使用 createApp 实用程序创建一个新的 h3 应用程序实例:

app.mjs
js
import { createApp } from 'h3'

const app = createApp()

设置全局选项

您可以在初始化应用时传递全局应用配置。

示例: 创建一个启用了详细日志记录的应用。

js
const app = createApp({
  debug: true,
})

设置全局钩子

初始化 h3 应用时,可以注册全局钩子:

  • onError
  • onRequest
  • onBeforeResponse
  • onAfterResponse

这些钩子会针对每个请求调用,可用于向您的应用添加全局逻辑,例如日志记录、错误处理等。

js
const app = createApp({
  onError: (error) => {
    console.error(error)
  },
  onRequest: (event) => {
    console.log('Request:', event.path)
  },
})

注册事件处理程序

您可以使用 app.use事件处理程序 注册到应用实例:

js
import { defineEventHandler } from 'h3'

app.use(
  '/hello',
  defineEventHandler((event) => {
    return 'Hello world!'
  }),
)

这会将事件处理程序注册到应用程序实例,并将针对以前缀/hello开头的每个请求调用。这意味着将针对/hello/hello/world/hello/123等调用事件处理程序。

您可以为同一路由定义多个事件处理程序。h3 将尝试按照注册顺序逐一调用它们,直到其中一个返回响应。这称为stack runner

js
app.use(
  '/',
  defineEventHandler((event) => {
    return 'First'
  }),
)
app.use(
  '/',
  defineEventHandler((event) => {
    return 'Second'
  }),
)

在此示例中,每个以/hello开头的请求都会调用第一个事件处理程序,而第二个事件处理程序永远不会被调用。

但是,如果您没有从第一个事件处理程序返回响应,则会调用第二个事件处理程序。这对于拥有 中间件 模式很有用。

js
app.use(
  '/',
  defineEventHandler((event) => {
    console.log('First')
    // 没有响应返回
  }),
)
app.use(
  '/',
  defineEventHandler((event) => {
    return 'Second'
  }),
)

如果所有处理程序都被调用但未返回任何响应,则 h3 将以 404 状态响应结束请求。

!NOTE 使用空的 returnreturn undefined 会产生 404 Not Found 状态响应。 同样,使用 return null 会产生 204 No Content 状态响应。

!TIP 使用 return {}return ""return true 做出明确响应。

事件处理程序选项

方法 use 接受可选的 options 对象作为第三个参数:

js
app.use(
  '/hello',
  defineEventHandler((event) => {
    return 'Hello world!'
  }),
  {
    // Options
  },
)

matcher

您可以定义自定义匹配器函数,以便拥有更高级的匹配请求逻辑,但比路由器更简单。

例如,您只能匹配奇数 URL,/1/3/5 等:

js
app.use(
  '/',
  defineEventHandler((event) => {
    return 'Odd URLs only'
  }),
  {
    match: (url) => {
      return url.substr(1) % 2
    },
  },
)

不要将自定义匹配器用作路由器。它不是为此目的而设计的。请改用 路由器

lazy

您可以提供一个异步函数,h3 将在第一次收到与路由匹配的请求时加载该函数。它对于动态导入很有用,可以减少启动时间。

js
app.use('/big', () => import('./big-handler'), { lazy: true })

这减少了启动时间,因为运行时启动服务器时需要加载和解析的代码更少。

Internals

这些细节主要供参考。切勿直接将内部组件用于生产应用程序!

h3 应用实例有一些附加属性。但是,除非您知道自己在做什么,否则通常不建议直接访问它们!

  • app.stack:当前注册的事件处理程序的有序数组。
  • 每个项目都有 routehandler 属性。
  • app.options:初始化应用时提供的全局选项对象。
  • app.handler:直接堆栈处理程序函数(直接调用不安全)。