基于 Thunks 打造的网页服务框架,修改自 Koa 框架。Thunks 是一个异步编程框架。
Toa 继承了 Koa 的 context、request、response ,但有以下区别:
- Toa 基于
thunks组织业务逻辑,支持node.js v0.10.x; - Toa 弱化中间件,也可以使用类似 koa 的中间件,但不支持级联(
yield* next),因为我认为级联与回调地狱类似,容易导致逻辑混乱; - Toa 提倡使用
thunks进行模块化开发,即一个模块接受输入,返回thunk; - 为安全起见,
context、request、response不包含app属性,即业务逻辑或模块无法访问顶层app对象; app不是Event对象,context变成了Event对象,方便业务逻辑内部用事件通信;app和context增加config属性,app可设置 config,业务逻辑可访问 config;- Toa 已嵌入异常处理逻辑,只需像
thunks一样处理或抛出异常即可(请参考 thunks 的作用域和异常处理设计),无需再使用 node.js 的domain系统。异常分两个层次:- 第一层是用户请求异常,业务逻辑可生成对应的错误信息,用
this.throw(error)抛出或直接throw抛出即可,Toa会自动将其响应给用户; - 第二层是系统异常,如业务逻辑抛出错误等,Toa也能自动捕获,对用户响应
500错误,并把异常交给app.onerror处理。
- 第一层是用户请求异常,业务逻辑可生成对应的错误信息,用
对于异步业务,应尽量用 thunks 封装才能捕获异常,如果确实不能用 thunks 封装,也可使用 context.emit('error', error)抛给应用处理。
不使用 generator ,可兼容 node.js v0.10.x:
var Toa = require('toa');
var app = Toa(function (Thunk) {
this.body = 'Hello World!\n-- toa';
});
app.listen(3000);使用 generator:
var Toa = require('toa');
var app = Toa(function* (Thunk) {
this.body = yield 'Hello World!\n-- ' + this.config.poweredBy;
});
app.config = {
poweredBy: 'Test'
};
app.listen(3000);使用中间件:
var Toa = require('toa');
var app = Toa();
app.use(function* () {
this.body = yield 'Hello World!\n-- toa';
});
app.listen(3000);使用自定义 server:
var https = require('https');
var fs = require('fs');
var Toa = require('toa');
var options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};
var server = https.createServer(options);
var app = Toa(server, function (Thunk) {
this.body = 'Hello World!\n-- toa';
});
app.listen(3000);文件服务:
var fs = require('fs');
var Toa = require('toa');
var app = Toa(function (Thunk) {
this.type = 'text';
this.body = fs.createReadStream(__dirname + '/simple.js', {encoding: 'utf8'});
});
app.listen(3000);npm install toa
var Toa = require('toa');server可以是 http server 或 https server。appBody有唯一参数Thunk,它的作用域带有onerror监听,能捕获任何异常。appBody中如果有异步逻辑,则应该封装在thunk函数、generator函数、generator对象或promise对象等中并return返回(与thunks或Promise类似)。options同 thunks 的 options,可以定义appBody中Thunk作用域的debug方法和onerror方法。其中onerror方法可用于对捕获异常进行初步加工处理,再return或throw给 Toa 内置的onResError处理。如果onerror返回true,则忽略该异常,继续执行后续业务逻辑。
var app = new Toa(server, function (Thunk) {
// body...
}, {
debug: function () {}
onerror: function (error) {}
});中文文档可参考 http://koajs.cn/ ,或者直接阅读 toa 源码。中间件函数、appBody 函数和 appBody 的 Thunk 派生的 thunk 函数,其 this 值均为 context。如:
this.req // node.js 原生 request stream
this.request // toa 封装后的 request stream
this.res // node.js 原生 response stream
this.response // toa 封装后的 request stream
this.cookies
this.throw
this.on
this.emit
// ...用于 cookie 加密的 Keygrip 对象或数组。
config 会被 context 继承,但 context 不能修改 app.config。
app.config = config;默认值:
{
proxy: false,
env: process.env.NODE_ENV || 'development',
subdomainOffset: 2,
poweredBy: 'Toa'
}返回 app,fn 必须是 thunk 函数或 generator 函数,函数中的 this 值为 context。
app.use(function (callback) {
// task
// this === context
callback(err, result);
})app.use(function* () {
// task
// this === context
yield result;
})app.onerror = function (error) {
// task
})返回 server,用法与 httpServer.listen 一致。
// 与 httpServer.listen 一致
app.listen(3000);