洋葱模型
- 关注koa-compose
/**
* @param {Object} context
* @return {Promise}
* @api public
*/
return function (context, next) {
// last called middleware #
let index = -1
return dispatch(0)
function dispatch (i) {
if (i <= index) return Promise.reject(new Error('next() called multiple times'))
index = i
let fn = middleware[i]
if (i === middleware.length) fn = next
if (!fn) return Promise.resolve()
try {
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)))
} catch (err) {
return Promise.reject(err)
}
}
}
异常处理
- 关注
koa/lib/application.js
的callback,handleRequest两个函数
callback() {
const fn = compose(this.middleware);
if (!this.listenerCount('error')) this.on('error', this.onerror);
const handleRequest = (req, res) => {
const ctx = this.createContext(req, res);
return this.handleRequest(ctx, fn);
};
return handleRequest;
}
handleRequest(ctx, fnMiddleware) {
const res = ctx.res;
res.statusCode = 404;
const onerror = err => ctx.onerror(err);
const handleResponse = () => respond(ctx);
onFinished(res, onerror);
return fnMiddleware(ctx).then(handleResponse).catch(onerror);
}
- ctx.onerror(err) => this.on(‘error’, this.onerror).
- koa-onerror重写了context.onerror函数
CO
- 基于
Generator
语法实现的库:用同步方式写异步逻辑,即async/await
的效果const co = require('co'); const promise = co(function* () { const res1 = yield 123; const res2 = yield 456; return res1 + res2; }); promise.then(val => { }).catch(err => { ... })
- ① 如何像async/await调用函数后
自动执行
? - ② 如何把yield expression的
expression执行结果
返回给res1、res2? - 图片来源
- ① 如何像async/await调用函数后
委托模式
将外部对象
接受到的操作
委托到内部属性
进行处理——可直接访问context.query、context.method等操作,实际上它是在context.request对象上的
- access和fluent方法的差异 :setter时fluent可以链式调用
const delegate = require('delegates'); const request = { query: 18, }; const response = { body: '18', }; const context = { request, response }; delegate(proto, 'request') .fluent('query') // getter const req = proto.query(); // setter (chainable) proto .query({ a: 1 }) .query({ b: 2 }); delegate(proto, 'response') .access('body') // getter const res = proto.body; // setter console.log(proto.body = 'set-body');
- 通过 defineGetter 和 defineSetter 分别设置 getter 和 setter:传递的函数的内部 this 指向原来的属性
let a = { nickName: 'HotDog' } a.__defineGetter__('name', function() { return this.nickName // 此处 this 仍然指向 a })