问题描述
刚刚面完阿里,问题中有一个问题是http模块如何实现对请求的同步处理,也就是一个请求处理完后再去处理另一个请求。面试时脑子短路,不够灵活没有想到如何实现,只说了在request事件中只调用同步的方法,明显不对嘛。哎,面完不一会,就想到了如何实现这个要求。
解决方案
开始只考虑到了http这个模块,没有考虑到net模块,其实主要实现是通过net来实现的,先通过net建立服务器,然后将请求保存在一个队列当中,然后从队列中慢慢的处理请求,就能够实现http的同步请求了。具体代码如下:
const http = require("http");
const net = require("net");
// 保存请求的队列,每个元素都是一个socket
let watingQueue = [];
// 当前处理的请求
let curtSocket = null;
let count = 0;
// 建立一个http服务器
let httpServer = http.createServer(function (req, res) {
// 延迟一秒中回复
setTimeout(function () {
res.end(`request: ${++count}`, "utf8");
}, 1000);
res.on("finish", function () {
curtSocket = null;
// 一个请求结束了,处理下一个请求
dealRequest();
});
});
// 建立一个tcp的服务器(http协议是建立在tcp协议上的)
net.createServer(function (socket) {
// 将请求压入列队
enqueueSocket(socket);
// 处理请求(如果现在真在处理的请求,不做任何处理)
dealRequest();
}).listen(4000);
function enqueueSocket (socket) {
watingQueue.push(socket);
}
function dealRequest () {
if (curtSocket != null || watingQueue.length <= 0) {
return;
}
curtSocket = watingQueue.shift();
httpServer.emit("connection", curtSocket);
}
测试
测试代码如下:
let http = require("http");
let count = 10;
for (var i = 0; i < count; ++i) {
request();
}
function request(i) {
let startTime = Date.now();
http.get("http://127.0.0.1:4000", function (res) {
let str = "";
res.setEncoding("utf8");
res.on("data", function (data) {
str += data;
});
res.on("end", function () {
console.log("++++++++++++++++++++");
console.log(str);
console.log(`time ${Date.now() - startTime}`);
console.log("--------------------\r\n");
});
});
}
测试结果如下: