python钩子函数装饰器_Fastify 系列教程二 (中间件、钩子函数和装饰器)

本文介绍了Fastify框架中中间件的使用,包括与Express中间件的兼容性和错误处理方式。同时,详细讲解了Fastify的钩子函数,如onRequest、preHandler、onResponse等,以及它们在请求生命周期中的作用。此外,还提到了装饰器和错误扩展功能,展示了如何通过decorate方法增强Fastify实例和Request/Reply对象的功能。
摘要由CSDN通过智能技术生成

Fastify 系列教程:

中间件

Fastify 提供了与 Express 和 Restify 中间件兼容的异步中间件引擎。

所以,Fastify 可以使用 Express 中间件。

注意:Fastify 中没有错误处理中间件(err, req, res, next)。如果需要处理中间件中的错误时,只需要调用 next(new Error('error message')) 即可,Fastify 会为你关闭请求并发送错误响应。

示例:

访问静态资源

配置 serve-static 访问静态资源。

目录结构:

public

|-css

|-js

|-jquery.js

|-images

views

app.js

app.js:

const serveStatic = require('serve-static')

const path = require('path')

fastify.use('/public', serveStatic(path.resolve(__dirname, 'public')))

此时,访问 localhost:3030/public/js/jquery.js 可以正确获得静态资源文件。

注意:中间件的请求和响应参数是原生 Nodejs Http 的 req 和 res,而路由中的 request 和 reply 是经过 Fastify 封装的,两者并不一样:

const fastify = require('fastify')()

fastify.use(function(req, res, next){

req.hello = "req.hello"

res.hello = "res.hello"

next()

})

fastify.use(function(req, res, next){

console.log('middle:', req.hello)

console.log('middle:', res.hello)

next()

})

fastify.get('/', function (request, reply) {

console.log('route:', request.hello)

console.log('route:', reply.hello)

reply.send({ hello: 'world' })

})

/*

middle: req.hello

middle: res.hello

route: undefined

route: undefined

*/

钩子函数

Fastify 中共有四个应用级钩子和一个路由级钩子。

四个应用级钩子:

onRequest(req, res, next)

preHandler(request, reply, next)

onResponse(res, next)

onClose(instance, done)

一个路由级钩子:

beforeHandler(request, reply, done)

注意 req、res 和 request、reply 的区别。

参数

描述

req

res

request

Fastify Request 接口

reply

Fastify Reply 接口

next

继续下一个 生命周期 任务

使用 addHook 方法添加钩子函数:

fastify.addHook('onRequest', (req, res, next) => {

// some code

next()

})

fastify.addHook('preHandler', (request, reply, next) => {

// some code

next()

})

fastify.addHook('onResponse', (res, next) => {

// some code

next()

})

如果在执行钩子函数时遇到错误,只需将其传递给 next(),并且 Fastify 将自动关闭请求并向用户发送相应的错误代码。

fastify.addHook('onRequest', (req, res, next) => {

next(new Error('some error'))

})

如果你希望传递一个自定义状态码,可以使用reply.code():

fastify.addHook('preHandler', (request, reply, next) => {

reply.code(500)

next(new Error('some error'))

})

onClose

onClose 是唯一不在生命周期中的钩子,当调用 fastify.close() 来停止服务器时,会触发此钩子,第一个参数是 Fastify 实例,第二个用来完成回调。

const fastify = require('fastify')()

fastify.get('/close', function(request, reply){

reply.type('text/html').send('

Close Server

')

fastify.close()

})

fastify.onClose(function(instance, done){

console.log('close db connection')

done()

})

访问 /close 时页面会显示 Close Server,并且控制台会输出:

[Running] node "/Users/lavyun/Code/node/learn-fastify/app.js"

close db connection

[Done] exited with code=0 in 8.524 seconds

在关闭数据库链连接之后,app.js 也被 exit 了。

preHandler 和 beforeHandler

preHandler 的受众对象是所有的路由,而 beforeHandler 的受众对象是某个特定的路由,另外,beforeHandler 总是在 preHandler 之后执行。

fastify.addHook('preHandler', (request, reply, done) => {

console.log('preHandler')

done()

})

fastify.get('/', {

beforeHandler: function (request, reply, done) {

console.log('beforeHandler')

done()

}

}, function (request, reply) {

reply.send({ hello: 'world' })

})

// preHandler

// beforeHandler

beforeHandler 也可以是一个函数数组:

fastify.addHook('preHandler', (request, reply, done) => {

console.log('preHandler')

done()

})

const firstBeforeHandler = (request, reply, done) => {

console.log('first beforeHandler')

done()

}

const secondBeforeHandler = (request, reply, done) => {

console.log('second beforeHandler')

done()

}

fastify.get('/', {

beforeHandler: [firstBeforeHandler, secondBeforeHandler]

}, function (request, reply) {

reply.send({ hello: 'world' })

})

// preHandler

// first beforeHandler

// second beforeHandler

装饰器

如果想为 Fastify 实例添加功能,可以使用 decorate 方法。

decorate 允许向 Fastify 实例添加新属性。可以是一个值、一个函数,也可以是一个对象或一个字符串等。

使用方法

decorate

只需要调用 decorate 函数,并且传入新属性的键和值即可。

fastify.decorate('utility', () => {

// something very useful

})

也可以定义其他类型的实例:

fastify.decorate('conf', {

db: 'some.db',

port: 3000

})

一旦定义了这个实例,可以通过传入的参数名称来得到该值:

fastify.utility()

console.log(fastify.conf.db)

装饰器不可以重新被覆盖,如果要定义一个已经存在的装饰器,decorate 将会抛出异常。

fastify.decorate("d1", 'd1')

fastify.decorate("d1", "d2") // Error

decorateReply

decorateReply 可以为 Reply 对象添加新属性。

fastify.decorateReply('utility', function () {

// something very useful

})

decorateRequest

decorateRequest 可以为 Request 对象添加新属性。

fastify.decorateRequest('utility', function () {

// something very useful

})

extendServerError

如果要扩展 服务器错误,可以使用此 API,必须传入一个返回值为对象的函数,该函数将接收原始的 Error 对象,并返回新Error 对象来扩展服务器错误。

fastify.extendServerError((err) => {

return {

timestamp: new Date()

}

})

/*

最终的错误对象格式:

{

error: String

message: String

statusCode: Number

timestamp: Date

}

*/

依赖

如果一个装饰器依赖于另一个装饰器,可以将其他装饰器声明为依赖。只需要添加一个字符串数组(表示所依赖的装饰器的名称)作为第三个参数即可:

fastify.decorate('utility', fn, ['greet', 'log'])

如果不满足依赖关系,那么 decorate 会抛出一个异常,但是不用担心:依赖关系检查会在服务器启动之前执行,所以在运行时不会发生错误。

hasDecorator

可以使用 hasDecorator 检查装饰器是否存在:

fastify.hasDecorator('utility')

Fastify 的更多使用将在接下来的博客中说明。

Tips:

访问 lavyun.cn 查看我的个人动态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值