1 function longPoll (data) {
2
3 //....此处省略**行
4
5 $.ajax({ cache: false
6 , type: "GET"
7 , url: "/recv"
8 , dataType: "json"
9 , data: { since: CONFIG.last_message_time, id: CONFIG.id }
10 , error: function () {
11 addMessage("", "long poll error. trying again...", new Date(), "error");
12 transmission_errors += 1;
13 //don't flood the servers on error, wait 10 seconds before retrying
14 setTimeout(longPoll, 10*1000);
15 }
16 , success: function (data) {
17 transmission_errors = 0;
18 //if everything went well, begin another request immediately
19 //the server will take a long time to respond
20 //how long? well, it will wait until there is another message
21 //and then it will return it to us and close the connection.
22 //since the connection is closed when we get data, we longPoll again
23 longPoll(data);
24 }
25 });
26 }
这是client.js中的一段代码,一看这段代码,大家应该立马想到两个字——“递归”。在longPoll方法中,再次调用longPoll方法,典型的递归调用。
根据这段代码的语义,可以看出,第一次加载时,会调用longPoll方法,异步向"/resv"获取值,如果成功了, 执行success的方法,立即再次调用longPoll方法。如果失败了,执行error函数,隔10秒中再次调用longPoll方法。当然,执行error方法有一定的次数限制,由变量transmission_errorsx控制。
大家可能会有一个疑问,这样一直递归循环获取数据,服务器会不会有很大的负担?在没有数据可获取的时候,也会一直这样循环吗?当然,答案时否定的!并且,nodejs利用自身的特点,很好的处理了这个问题。接着往下看:
var MESSAGE_BACKLOG = 200,
SESSION_TIMEOUT = 60 * 1000;
var channel = new function () {
var messages = [],
callbacks = [];
this.appendMessage = function (nick, type, text) {
var m = { nick: nick
, type: type // "msg", "join", "part"
, text: text
, timestamp: (new Date()).getTime()
};
switch (type) {
case "msg":
sys.puts("<" + nick + "> " + text);
break;
case "join":
sys.puts(nick + " join");
break;
case "part":
sys.puts(nick + " part");
break;
}
messages.push( m );
while (callbacks.length > 0) {
//shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值
callbacks.shift().callback([m]);
}
while (messages.length > MESSAGE_BACKLOG)
messages.shift();
};
this.query = function (since, callback) {
var matching = [];
for (var i = 0; i < messages.length; i++) {
var message = messages;
if (message.timestamp > since)
matching.push(message)
}
if (matching.length != 0) {
callback(matching);
} else {
callbacks.push({ timestamp: new Date(), callback: callback });
}
};
// clear old callbacks
// they can hang around for at most 30 seconds.
setInterval(function () {
var now = new Date();
while (callbacks.length > 0 && now - callbacks[0].timestamp > 30*1000) {
callbacks.shift().callback([]);
}
}, 3000);
};
channel中定义了两个变量,两个方法,还有一个每隔3秒执行一次的setInterval函数。 首先看query方法,
query方法接收两个参数: