Skip to content
Our Sponsors
Open in Anthropic

title: 生命周期 - Elysia 教程 layout: false search: false authors: [] head: - - meta - property: 'og:title' content: 生命周期 - Elysia 教程

- - meta
  - name: 'description'
    content: 生命周期钩子是在请求-响应周期中的特定事件上执行的函数。

- - meta
  - property: 'og:description'
    content: 生命周期钩子是在请求-响应周期中的特定事件上执行的函数。

生命周期

生命周期钩子是在请求-响应周期中的特定事件上执行的函数。

它们允许您在特定时间点运行自定义逻辑

这对于日志记录、身份验证等任务非常有用。

要注册生命周期钩子,您可以将其传递给路由方法的第三个参数:

typescript
import { Elysia } from 'elysia'

new Elysia()
	.get('/1', () => 'Hello Elysia!')
	.get('/auth', () => {
		console.log('This is executed after "beforeHandle"')

		return 'Oh you are lucky!'
	}, {
		beforeHandle({ request, status }) {
			console.log('This is executed before handler')

			if(Math.random() <= 0.5)
				return status(418)
		}
	})
	.get('/2', () => 'Hello Elysia!')

beforeHandle 返回一个值时,它将跳过处理程序并返回该值。

这对于身份验证之类的事情很有用,如果用户未通过身份验证,您希望返回 401 Unauthorized 响应。

参阅 生命周期前置处理 以获取更详细的解释。

钩子

一个拦截生命周期事件的函数。因为函数**"钩住"**了生命周期事件

钩子可以分为两种类型:

  1. 本地钩子 - 在特定路由上执行
  2. 拦截器钩子 - 在注册钩子后的每个路由上执行

本地钩子

本地钩子在特定路由上执行。

要使用本地钩子,您可以将钩子内联到路由处理程序中:

typescript
// 与之前的代码片段类似
import { Elysia } from 'elysia'

new Elysia()
	.get('/1', () => 'Hello Elysia!')
	.get('/auth', () => {
		console.log('Run after "beforeHandle"')

		return 'Oh you are lucky!'
	}, {
		// 这是一个本地钩子
		beforeHandle({ request, status }) {
			console.log('Run before handler')

			if(Math.random() <= 0.5)
				return status(418)
		}
	})
	.get('/2', () => 'Hello Elysia!')

拦截器钩子

将钩子注册到当前实例中,在钩子被调用之后的每个处理程序

要添加拦截器钩子,您可以使用 .on 后跟一个生命周期事件:

typescript
import { Elysia } from 'elysia'

new Elysia()
	.get('/1', () => 'Hello Elysia!')
	.onBeforeHandle(({ request, status }) => {
		console.log('This is executed before handler')

		if(Math.random() <= 0.5)
			return status(418)
	})
	// "beforeHandle" 被应用
	.get('/auth', () => {
		console.log('This is executed after "beforeHandle"')

		return 'Oh you are lucky!'
	})
	// "beforeHandle" 也被应用
	.get('/2', () => 'Hello Elysia!')

与本地钩子不同,拦截器钩子会将钩子添加到注册钩子之后的每个路由。

练习

让我们将两种类型的钩子付诸实践。

  1. Authentication

    Let's add a simple authentication middleware to GET "/auth" endpoint using beforeHandle hook. If query `name` is provided, we will let the request pass, otherwise we will return 401 status.

  2. Interceptor Hook

    Now, let's create another endpoint GET "/profile" that has the same logic with authentication. We can refactor our code by using interceptor hook to avoid duplication.

Show answer

我们可以使用 beforeHandle 在请求到达处理程序之前拦截它,并使用 status 方法返回响应。

typescript
import { Elysia } from 'elysia'

new Elysia()
	.onBeforeHandle(({ query: { name }, status }) => {
		if(!name) return status(401)
	})
	.get('/auth', ({ query: { name = 'anon' } }) => {
		return `Hello ${name}!`
	})
	.get('/profile', ({ query: { name = 'anon' } }) => {
		return `Hello ${name}!`
	})
	.listen(3000)
  • index.ts