@JunQiu
2018-09-18T17:31:18.000000Z
字数 6090
阅读 1858
summary_2018/06
designIdea
language_node
fastify
1、日常工作
2、技术学习
Incoming Request
│
└─▶ Routing(路由匹配)
│
└─▶ Instance Logger(实例化log)
│
404 ◀─┴─▶ onRequest Hook(执行onRequest Hook)
│
4**/5** ◀─┴─▶ run Middlewares(执行中间件函数)
│
4**/5** ◀─┴─▶ Parsing(解析请求对象req->request)
│
415 ◀─┴─▶ Validation(验证)
│
400 ◀─┴─▶ preHandler Hook
│
4**/5** ◀─┴─▶ beforeHandler(在handler执行前执行)
│
4**/5** ◀─┴─▶ User Handler(执行请求处理函数)
│
└─▶ Reply(响应)
│
└─▶ onSend Hook
│
4**/5** ◀─┴─▶ Outgoing Response(output响应)
│
└─▶ onResponse Hook
###
1、如果在执行钩子过程中出现错误,只需将它传递给next()并且Fastify将自动关闭请求并将适当的错误代码发送给用户。(自定义错误代码传递给用户,使用reply.code())
2、可以在到达路由处理程序之前响应请求。比如认证钩子。如果您正在使用onRequest或中间件,请使用res.end。如果您正在使用preHandler挂钩,请使用reply.send。
3、当fastify.close()被调用来停止服务器时触发。第一个参数是Fastify实例,第二个参数是done回调函数(结束回调)。
4、beforeHandler不是标准钩子preHandler,在路由中注册,只会在指定的路由中执行。
5、Application Hooks('onClose','onRoute')
fastify.addHook('onRequest', (req, res, next) => {
// some code
next()
})
//注意钩子的参数,不同的阶段的参数代表的值不一样
fastify.addHook('onRequest', async (req, res) => {
// some code
await asyncMethod()
// error occurred
if (err) {
throw new Error('some errors occurred.')
}
return
})
fastify.addHook('preHandler', async (request, reply) => {
// some code
await asyncMethod()
// error occurred
if (err) {
throw new Error('some errors occurred.')
}
return
})
fastify.addHook('onSend', async (request, reply, payload) => {
// some code
await asyncMethod()
// error occurred
if (err) {
throw new Error('some errors occurred.')
}
return
})
fastify.addHook('onResponse', async (res) => {
// some code
await asyncMethod()
// error occurred
if (err) {
throw new Error('some errors occurred.')
}
return
})
## 应用级别
module.exports = function (req, res, next) {
next('test')
}
fastify.use(methodname)
##若需限制中间件到特殊路径
//只需将路径作为第一个参数传递use
// Single path
fastify.use('/css', serveStatic(path.join(__dirname, '/assets')))
// Wildcard path
fastify.use('/css/*', serveStatic(path.join(__dirname, '/assets')))
// Multiple paths
fastify.use(['/css', '/js'], serveStatic(path.join(__dirname, '/assets')))
Tips: not support routes with parameters, (eg: /user/:id/comments) and wildcard is not supported in multiple paths.
## 如果需要传入参数(参考express)
const mid=require('./test1')
fastify.use(mid(222))
// mid
module.exports = options=>function (req, res, next) {
next(options)
}
Tips:中间件的请求和响应参数是原生 Nodejs Http 的 req 和 res,而路由中的 request 和 reply 是经过 Fastify 封装的,两者并不一样
## 以插件的形式注入,register会创造新的上下文,可以使用fastify-plugin解决
// pl
const fp = require('fastify-plugin')
module.exports = fp(function (fastify, opts, next) {
const mid = function (req, res, next) {
next(11111)
}
fastify.use(mid)
next()
})
fastify.register(pl)
### decorateReply(you want to add new methods to the Reply core object. )
fastify.decorateReply('utility', function () {
// something very useful
})
//decorateRequest
### 依赖(添加一个字符串数组(表示您所依赖的装饰器的名称)作为第三个参数)
fastify.decorate('utility', fn, ['greet', 'log'])
##使用
fastify.register(plugin, [options])
options:logLevel、prefix
//创建一个插件非常简单,只需要创建一个带有三个参数的fastify实例,一个选项对象和下一个回调函数。
Example:
fastify.register(require('./routes/v1/users'), { prefix: '/v1' })
// routes/v1/users.js
module.exports = function (fastify, opts, next) {
fastify.get('/user', handler_v1)
next()
}
Tips:fastify, opts, next
## register产生新的上下文,然后传递给下一代
fastify.register((instance, opts, next) => {
instance.decorate('util', (a, b) => a + b)
console.log(instance.util('that is ', ' awesome'))
next()
})
fastify.register((instance, opts, next) => {
console.log(instance.util('that is ', ' awesome')) // 抛出异常
next()
})
node_module.export_export
##作为属性
module.exports = {
};
//exports被赋值,导出失败
##方式二
module.exports.xx=xx;
exports.xx=xx;
### export
export var firstName = 'Michael';
export var lastName = 'Jackson';
#or
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export {firstName, lastName, year};
##别名
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
};
##export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系
// 报错
export 1;
// 报错
var m = 1;
export m;
// 写法一
export var m = 1;
// 写法二
var m = 1;
export {m};
// 写法三
var n = 1;
export {n as m};
###export default命令,为模块指定默认输出
//export default命令只能使用一次
//可以指定任意名字,import不要大括号
//export default命令其实只是输出一个叫做default的变量
// 正确
export var a = 1;
// 正确
var a = 1;
export default a;(赋值给default)
// 错误
export default var a = 1;
### import
//import语句是 Singleton 模式(加载多个只会加载一个)
import {firstName, lastName, year} from './profile.js';
import * as circle from './circle';
##别名
import { lastName as surname } from './profile.js';
##import命令输入的变量都是只读的,因为它的本质是输入接口。
import {a} from './xxx.js'
a = {}; // Syntax Error : 'a' is read-only;
#禁止这种操作,本意用于提供只读,难排查错误
import {a} from './xxx.js'
a.foo = 'hello'; // 合法操作
##export、import复合写法
export { foo, bar } from 'my_module';
// 可以简单理解为
import { foo, bar } from 'my_module';
export { foo, bar };
回调函数和钩子函数(hook)