Expressjs/finished Code Reading
- 功能: 在请求关闭,完成, 或者出错时执行回调
- 用例: 清除传输流。例如为了防止文件描述符泄漏,在socket出错时, 你会想要将文件流摧毁
从一个koa例子开始
1
2
3
4
5
6
7
| var onFinished = require('finished');
function* () {
var stream = this.body = fs.createReadStream('thingie.json');
onFinished(this, function(err) {
stream.destroy();
})
}
|
再看finished的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| module.exports = function finished (thingie, callback) {
/*
* 主要需要監測socket和res的事件
*/
var socket = thingie.socket || thingie;
var res = thingie.res || thingie;
/*
* res完成或者socket不可寫的時候, 直接執行callback, 返回thingie
*/
if ( res.finished || !socket.writable) {
defer(callback);
return thingie;
};
/*
* 第一次運行時listener 和 res.__onFinished 是不存在的
*/
var listener = res.__onFinished;
if (!listener || !listener.queue) {
listener = res.__onFinished = function onFinished(err) {
if (res.__onFinished === listener) res.__onFinished = null; // 這句表明每次給listener 賦完值, res.__onFinished = null;
var queue = listener.queue || [];
while (queue.length) queue.shift()(err)
}
listerner.queue = [];
first([
[socket, 'error', 'close'],
[res, 'finish'],
], listener); // 看[first](https://github.com/jonathanong/ee-first)模块解析: 主要功能在监听到指定的事件的第一件时,触发响应回调, 并清除移除所有的监听。
}
listener.queue.push(callback);
return thingie;
}
|
想要具体看finish的应用场景,其实在单元测试里有很多具体的例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| describe('when the request finished', function () {
it('should execute the callback when called after finish', function(done){
var server = http.createServer(function(req, res){
onFinished(res, function(){
//第4步
onFinished(res, done); // 第5步
}) // 第2步
setTimeout(res.end.bind(res), 0); // 第3步
}) // 第 0 步
server.listen(function(){
var port = this.address().port;
http.get('http://127.0.0.1:' + port, function(){
res.resume();
res.on('close', server.close.bind(server));
}) //第1步
})
})
})
|