使用http模块
实现步骤
- 收集中间件
middlewareList
class SimpleKoa2 {
constructor(){
this.middlewareList = []
}
use(fn){
this.middlewareList.push(fn)
}
}
- 监听端口
listen
class SimpleKoa2 {
/* ... */
listen(...args){
const server = http.createServer(this.callback())
server.listen(...args)
}
}
- 组合中间件实现
next()原理
class SimpleKoa2 {
/* ... */
listen(...args) {
const server = http.createServer(this.callback())
}
callback() {
// 组装中间件
const fn = this.compose(this.middlewareList)
return (req, res) => {
const ctx = this.createContext(req, res)
return this.handleRequest(ctx, fn)
}
}
compose(middlewares) {
return (ctx) => {
function dispatch(i) {
const fn = middlewares[i]
try {
return Promise.resolve(fn(ctx, dispatch.bind(null, i + 1)))
} catch (err){
return Promise.reject(err)
}
}
// 从第一个中间件开始
return dispatch(0)
}
}
// 组合 ctx
createContext(req, res) {
const ctx = { req, res }
ctx.query = req.query
return ctx
}
// 执行中间件
handleRequest(ctx, fn) {
return fn(ctx)
}
}
总结
-
收集所有使用的中间件
-
核心: 实现
next()执行所有匹配的中间件
const http = require('http)
class SimpleKoa2 {
constructor() {
this.middlewareList = []
}
// 收集中间件
use(fn) {
this.middlewareList.push(fn)
}
listen(...args) {
const server = http.createServer(this.callback())
server.listen(...args)
}
callback() {
// 组装中间件
const fn = this.componse(this.middlewareList)
return (req, res) => {
// 生成 ctx
const ctx = createContext(req, res)
// 执行中间件
return this.handle(ctx, fn)
}
}
componse(middlewares) {
return (ctx) => {
function dispatch(i) {
const fn = middlewares[i]
//
try {
// 传入下一个中间件 dispatch(null, i+1 )
return Promise.resolve(fn(ctx, dispatch(null, i+1 )))
} catch (err) {
return Promise.reject(err)
}
}
return dispatch(0) // 返回第一个中间件函数
}
}
createContext(req, res) {
const ctx = { req, res }
ctx.query = req.query
return ctx
}
handle(ctx, fn) {
fn(ctx)
}
}