如何从头实现一个node.js的koa框架

2020-06-17 06:09:13易采站长站整理

let fn = this.compose();
return fn(ctx).then(respond);
};
}
// ...省略后面
}
module.exports = Application;

可以看到,首先对app.use进行改造了,每次调用app.use,就向this.middlewares中push一个回调函数。然后增加了一个compose()方法,利用我们前文分析的原理,对middlewares数组中的函数进行组装,返回一个最终的函数。最后,在callback()方法中,调用compose()得到最终回调函数,并执行。

改写example.js验证一下中间件机制:


let simpleKoa = require('./application');
let app = new simpleKoa();
let responseData = {};
app.use(async (ctx, next) => {
responseData.name = 'tom';
await next();
ctx.body = responseData;
});
app.use(async (ctx, next) => {
responseData.age = 16;
await next();
});
app.use(async ctx => {
responseData.sex = 'male';
});
app.listen(3000, () => {
console.log('listening on 3000');
});
// 返回{ name: "tom", age: 16, sex: "male"}

例子中一共三个中间件,分别对responseData增加了name, age, sex属性,最后返回该数据。

至此,一个koa框架基本已经浮出水面了,不过我们还需要进行最后一个主线的分析:错误处理。

主线四:错误处理

一个健壮的框架,必须保证在发生错误的时候,能够捕获错误并有降级方案返回给客户端。但显然现在我们的框架还做不到这一点,假设我们修改一下例子,我们的中间件中,有一个发生错误抛出了异常:


let simpleKoa = require('./application');
let app = new simpleKoa();
let responseData = {};
app.use(async (ctx, next) => {
responseData.name = 'tom';
await next();
ctx.body = responseData;
});
app.use(async (ctx, next) => {
responseData.age = 16;
await next();
});
app.use(async ctx => {
responseData.sex = 'male';
// 这里发生了错误,抛出了异常
throw new Error('oooops');
});
app.listen(3000, () => {
console.log('listening on 3000');
});

这个时候访问浏览器,是得不到任何响应的,这是因为异常并没有被我们的框架捕获并进行降级处理。回顾我们application.js中的中间件执行代码:


// application.js
// ...
callback() {
return (req, res) => {
let ctx = this.createContext(req, res);
let respond = () => this.responseBody(ctx);
let fn = this.compose();
return fn(ctx).then(respond);
};
}
// ...

其中我们知道,fn是一个async函数,执行后返回一个promise,回想promise的错误处理是怎样的?没错,我们只需要定义一个onerror函数,里面进行错误发生时候的降级处理,然后在promise的catch方法中引用这个函数即可。