我正在使用以下内容进行基本的长轮询:
var http = require('http');
var url = require('url');
var Memcached = require('memcached');
var libAS = require('./libAS');
var cache = new Memcached('localhost:11211');
http.createServer(function(request,response) {
response.writeHead(200, { 'Content-Type': 'text/plain' , 'Access-Control-Allow-Origin' : 'http://localhost'});
var url_parts = url.parse(request.url,true);
var querystring = url_parts.query;
if(!libAS.exists(querystring.channel_id) || !libAS.exists(querystring.workstamp) || !libAS.exists(querystring.subscriber))
{
response.end("Invalid Request");
}
var channel = new Channel(querystring.channel_id,cache);
//get workstamp
channel.getWorkstamp(function(workstamp) {
if(!workstamp)
{
//If workstamp not found
response.end("Channel invalid");
}
else
{
channel.checkSubscriber(querystring.subscriber,function(valid) {
if(!valid)
{
response.end("Channel invalid");
}
else
{
channel.startLoop(querystring.workstamp,response);
}
});
}
});
}).listen(1111,'localhost');
//----------------------------------CHANNEL HANDLING----------------------------------------//
var Channel = function(id,cache) {
this.cache = cache;
this.id = id;
this.loopLimit = 10; // Almost equal to seconds.
this.loopCount = 0;
this.WSDump = null;
this.getWorkstamp(function(workstamp){
this.WSDump = workstamp;
});
};
Channel.prototype.startLoop = function(workstamp,response) {
_self = this;
_self.WSDump = workstamp;
_self.checkUpdates(workstamp,function(updated,current_workstamp){
if(updated)
{
console.log("Updated. Ending");
}
else
{
if(_self.loopCount<_self.loopLimit)
{
console.log("Not Updated. Continuing with workstamp "+current_workstamp);
_self.loopCount++;
_self.loop(current_workstamp,response);
}
else
{
console.log("Limit reached. Updating current workstamp "+current_workstamp);
_self.endResponse(200,response);
}
}
});
};
Channel.prototype.loop = function(workstamp,response) {
_self = this;
_self.WSDump = workstamp;
setTimeout(function() {
_self.checkUpdates(workstamp,function(updated,current_workstamp){
if(updated)
{
console.log("Updated. Ending");
}
else
{
if(_self.loopCount<_self.loopLimit)
{
console.log("Not Updated. Continuing with workstamp "+current_workstamp);
_self.loopCount++;
_self.loop(current_workstamp,response);
}
else
{
console.log("Limit reached. Updating current workstamp "+current_workstamp);
_self.endResponse(200,response);
}
}
});
},1000);
};
Channel.prototype.endResponse = function(code,response) {
if(code === 200)
{
json = {"status":200};
}
response.end(JSON.stringify(json));
};
Channel.prototype.checkUpdates = function(workstamp,callback) {
this.getWorkstamp(function(current_workstamp) {
if(!current_workstamp) callback(false);
else
{
if(workstamp == current_workstamp)
{
callback(false,current_workstamp);
}
else
{
callback(true,current_workstamp);
}
}
});
};
Channel.prototype.getWorkstamp = function(callback) {
this.cache.get(this.id+':channel'+':workstamp',function(err,data){
if(err)
{
console.log(err);
callback(false);
}
else
{
callback(data);
}
});
};
Channel.prototype.checkSubscriber = function(id,callback) {
this.cache.get(this.id+':channel:subscriptions',function(err,data) {
if(err)
{
console.log(err);
callback(false);
}
else
{
data = getArray(data);
for(i=0;i<data.length;i++)
{
if(data[i]['id']==id)
{
callback(true);
break;
}
else
{
if(i == (data.length-1))
{
callback(false);
break;
}
}
}
}
});
};
Channel.prototype.fetch = function(callback) {
this.cache.get(this.id+':channel',function(err,data){
if(err)
{
console.log(err);
callback(false);
}
else
{
callback(getArray(data));
}
});
};
var getArray = function(obj) {
return JSON.parse(obj.toString());
};
当只连接一个客户端时,它就像我想要的那样运行,也就是说,进程在10秒内结束。但是当我同时通过2个客户发送请求时,流程在20s结束。如果是3,那么30s。谁能告诉我这里的问题?我以为每个请求会分别执行相同的代码吗? (PS,我不是很擅长javascript,我为没有文档的代码道歉,我有点匆忙)。
答案 0 :(得分:0)
解决了它。循环计算在某处混淆的地方。我更改了它以删除原型函数,并使用这样的简单函数:
var http = require('http');
var url = require('url');
var Memcached = require('memcached');
var libAS = require('./libAS');
var cache = new Memcached('localhost:11211');
http.createServer(function(request,response) {
response.writeHead(200, { 'Content-Type': 'text/plain' , 'Access-Control-Allow-Origin' : 'http://localhost'});
var url_parts = url.parse(request.url,true);
var querystring = url_parts.query;
var channel_id = querystring.channel_id;
var subscriber = querystring.subscriber;
var workstamp = querystring.workstamp;
if(!libAS.exists(querystring.channel_id) || !libAS.exists(querystring.workstamp) || !libAS.exists(querystring.subscriber))
{
response.end("Invalid Request");
}
fetch(channel_id,cache,function(data){
if(checkEmpty(data)) endResponse(0,workstamp,response);
else
{
checkSubscriber(channel_id,subscriber,cache,function(valid){
if(!valid) endResponse(-1,workstamp,response);
else
{
startLoop(channel_id,workstamp,response,cache);
}
});
}
});
}).listen(1111,'localhost');
//----------------------------------CHANNEL HANDLING----------------------------------------//
var LoopProp = function(){
this.count = 0;
this.limit = 10;
};
var startLoop = function(channel_id,workstamp,response,cache) {
var current_workstamp = workstamp;
var prop = new LoopProp();
checkUpdates(channel_id,current_workstamp,cache,function(updated,new_workstamp){
if(updated)
{
console.log("Updated. Ending - Old workstamp:"+current_workstamp+" - New workstamp:"+new_workstamp);
endResponse(1,new_workstamp,response);
}
else
{
current_workstamp = new_workstamp;
console.log("Not updated. Workstamp : "+current_workstamp);
loop(channel_id,current_workstamp,prop,response,cache);
}
});
};
var loop = function(channel_id,workstamp,prop,response,cache) {
var current_workstamp = workstamp;
setTimeout(function(){
checkUpdates(channel_id,current_workstamp,cache,function(updated,new_workstamp){
if(updated)
{
console.log("Updated. Ending - Old workstamp:"+current_workstamp+" - New workstamp:"+new_workstamp);
endResponse(1,new_workstamp,response);
}
else
{
current_workstamp = new_workstamp;
console.log("Not updated. Workstamp : "+current_workstamp+" - Loop count : "+prop.count);
if(prop.count==(prop.limit-1))
{
endResponse(0,current_workstamp,response);
}
else
{
prop.count++;
loop(channel_id,current_workstamp,prop,response,cache);
}
}
});
},1000);
};
var endResponse = function(code,workstamp,response) {
response.end(JSON.stringify({'status':code,'workstamp':workstamp}));
};
var checkUpdates = function(channel_id,workstamp,cache,callback) {
getWorkstamp(channel_id,cache,function(current_workstamp) {
if(!current_workstamp) callback(false);
else
{
if(workstamp == current_workstamp)
{
callback(false,current_workstamp);
}
else
{
callback(true,current_workstamp);
}
}
});
};
var getWorkstamp = function(channel_id,cache,callback) {
cache.get(channel_id+':channel'+':workstamp',function(err,data){
if(err)
{
console.log(err);
callback(false);
}
else
{
callback(data);
}
});
};
var checkSubscriber = function(channel_id,subscriber,cache,callback) {
cache.get(channel_id+':channel:subscriptions',function(err,data) {
if(err)
{
console.log(err);
callback(false);
}
else
{
data = getArray(data);
for(i=0;i<data.length;i++)
{
if(data[i]['id']==subscriber)
{
callback(true);
break;
}
else
{
if(i == (data.length-1))
{
callback(false);
break;
}
}
}
}
});
};
var fetch = function(channel_id,cache,callback) {
cache.get(channel_id+':channel',function(err,data){
if(err)
{
console.log(err);
callback(false);
}
else
{
callback(data);
}
});
};
var checkEmpty = function(obj) {
if(obj == ':') return true; else return false;
};
var getArray = function(obj) {
return JSON.parse(obj.toString());
};