之前只用event機制來實做流程,會有控制不夠精確的問題,所以再來改一下。
問題
之前的流程修改雖然通過測試,但是總覺得還沒有兼顧到夠完整的狀況,所以需要在仔細分析一下需求。
調整
流程的修改大概如下:
但是要兼顧到非同步執行...又要在適當時機trigger下一個流程,做法會有點複雜,需要有一個方法等待處理結束,然後再處理結束時,觸發下一個流程。這個時候單靠簡單的Javascript有點難控制,需要用額外的方法來處理。
實做
先加入一個wait函數,長這樣:
var wait = function(callbacks, req, res, done) {
var counter = callbacks.length;
var results = [];
var next = function(result) {
results.push(result);
if(--counter < 1) {
done(results);
}
};
if(counter === 0) {
done(results);
return;
}
for(var i = 0; i < callbacks.length; i++) {
callbacks[i](req, res, next);
}
};
然後執行傳入的callbacks(也就是handlers),全部執行結束時,才觸發dispatch事件。dispatch事件會監看一個flag變數:dispatched,如果已經觸發過就不會再執行一次。這樣可以保證在header中觸發的dispatch不會再次執行。
不過在handler的定義中,除了傳給它request, response參數,還必須傳next這個callback,讓他在執行完畢後呼叫。
"cookieHandler": function(request, response, next) {
if(request.headers.cookie) {
request.cookie = tools.cookieParser(request.headers.cookie);
} else {
request.cookie = {};
}
next();
}
伺服器的主程式調整成這樣:
var http = require('http'),
tools = require('./tools');
var count = 0;
var wait = function(callbacks, req, res, done) {
var counter = callbacks.length;
var results = [];
var next = function(result) {
results.push(result);
if(--counter < 1) {
done(results);
}
};
if(counter === 0) {
done(results);
return;
}
for(var i = 0; i < callbacks.length; i++) {
callbacks[i](req, res, next);
}
};
module.exports = function(conf) {
var pre = [];
var server = http.createServer(function(request, response) {
var dispatched = false;
var post = false;
var precount = 0;
//tools.cookieHandler(request, response);
console.log(process.pid + '::' + (++count) + ': ' + process.memoryUsage().heapUsed);
//this.emit('pre', request, response);
wait(pre, request, response, function(){
server.emit('dispatch', conf, request, response, function(err, realpath, data) {
if(dispatched) {
return;
} else {
dispatched = true;
}
if(err) {
console.log(process.pid + '::' + realpath + ' not exists.');
response.writeHead(404, {"Content-Type":"text/html"});
response.end('<h1>404: Request resource not found.</h1>');
} else {
console.log(process.pid + '::' + realpath + ' exists.');
response.writeHead(200, {
"Content-Type": data.type,
"Content-Length": data.data.length
});
response.end(data.data);
}
server.emit('post', request, response);
});
});
});
this.listen = function(port, addr) {
server.listen(port, addr);
return this;
};
this.close = function() {
server.close();
return this;
};
this.host = tools.hostHandler;
this.handle = function(hook, handler) {
switch(hook) {
case 'pre':
pre.push(handler);
break;
case 'dispatch':
server.on('dispatch', handler);
break;
case 'post':
server.on('post', handler);
}
};
this.handle('dispatch', tools.dispatch);
};
跑一下整合測試,可以通過,應該OK了吧?碰到問題再來調整好了,目前還沒有足夠的pre dispatch handler可以測試。
今天的範例檔fillano-evolve-v0.0.16-0-g0438ff0.zip,目前版本是v0.0.16。