node.js实现的Long Polling例子
前台页面使用jquery的jsonp来进行轮询。后端node.js监听的端口是8124
index.html
<!Doctype html>
<html>
<head>
<title>Long Polling in node.js</title>
<meta http-equiv='content-type' content='text/html; charset=utf-8'>
<style type='text/css'>
* {margin:0; padding:0;}
body {background-color:#fff;}
#infoContainer{margin:40px; padding:10px; font-size:14px; border:1px solid #eee;}
</style>
</head>
<body>
<div id='infoContainer'>loading...</div>
<script type='text/javascript' src='js/jquery.js'></script>1:2:3: <script type='text/javascript'>4:5: function callPolling() {6: $.ajax({7: url: 'http://localhost:8124/?callback=pollingCallback',8: dataType : 'jsonp',9: jsonp : 'kk',10: timeout : 70 * 1000,11: complete : function() {12: callPolling();13: }14: })15: }16:17: function pollingCallback(str) {18: $("#infoContainer").html(str);19: }20:21: $(callPolling);22:</script>
</body>
</html>
后台用node.js实现的polling.js
var http = require('http'),
fs = require('fs');http.createServer(function(req, res) {checkFile(req, res);
}).listen(8124);
var filepath = 'E:/Node_app/file/a.txt';
function checkFile(req, res) { var reqUrl = req.url;var callbackFnName = null;
if (/callback=([^&]+)/.test(reqUrl)) { callbackFnName = RegExp['$1'];}
var date = new Date();
if (date - req.socket._idleStart.getTime() > 60 * 1000) { res.writeHead(200, {'Content-Type' : 'text/plain',
'Access-Control-Allow-Origin' : '*'
});
res.write(callbackFnName + "('ok')", 'utf8');
res.end();
}
fs.stat(filepath, function(err, stats) { if (err) { res.writeHead(200, {'Content-Type' : 'text/plain',
'Access-Control-Allow-Origin' : '*'
});
res.write(callbackFnName + "('Error')", 'utf8');
res.end();
return false;
}
//文件是在请求过来之后发生更改的 if (stats.mtime.getTime() > req.socket._idleStart.getTime()) {fs.readFile(filepath, 'utf8', function(err, data) {
res.writeHead(200, {'Content-Type' : 'text/plain',
'Access-Control-Allow-Origin' : '*'
});
res.write(callbackFnName + "('" + data + "')", 'utf8');
res.end();
return false;
});
}
});
setTimeout(function() {checkFile(req, res);
}, 10 * 1000);
}
/** * 时间对象的格式化; */Date.prototype.format = function (format) { /* * eg:format="YYYY-MM-dd hh:mm:ss"; */ var o = {"M+": this.getMonth() + 1, //month
"d+": this.getDate(), //day
"h+": this.getHours(), //hour
"m+": this.getMinutes(), //minute
"s+": this.getSeconds(), //second
"q+": Math.floor((this.getMonth() + 3) / 3), //quarter
"S": this.getMilliseconds() //millisecond
}
if (/(Y+)/i.test(format)) {format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
}
for (var k in o) {
if (new RegExp("(" + k + ")").test(format)) {
format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
}
}
return format;}
setInterval(function() {fs.writeFileSync(filepath, '当前时间:' + new Date().format('YYYY-MM-dd hh:mm:ss'), 'utf8');
}, 1000 * 1);
监听文件发生改变,就立即输出内容给前台页面请求。
这里有关于文件atime、ctime、mtime三者区别的详细介绍>>
关于File的元信息,可以参考这里(stat详解)>>
在控制台上打印出的req信息
{ socket: { _handle: {writeQueueSize: 0,
owner: [Circular],
onread: [Function: onread]
},
_pendingWriteReqs: 0,
_flags: 0,
_connectQueueSize: 0,
destroyed: false, errorEmitted: false,bytesRead: 602,
_bytesDispatched: 0,
allowHalfOpen: true, writable: true, readable: true, _paused: false, server: {_connections: 1,
connections: [Getter / Setter],
allowHalfOpen: true,_handle: [Object],
_events: [Object],
httpAllowHalfOpen: false, _connectionKey: '4:0.0.0.0:8124'},
_events: {drain: [Function: ondrain],
timeout: [Object],
error: [Function],
close: [Object]
},
_idleTimeout: 120000,
_idleNext: {_idleNext: [Circular],
_idlePrev: [Circular],
ontimeout: [Function]
},
_idlePrev: {_idleNext: [Circular],
_idlePrev: [Circular],
ontimeout: [Function]
},
_idleStart: Tue Jul 24 2012 01: 18: 39 GMT + 0800(中国标准时间),
parser: {_headers: [],
_url: '',onHeaders: [Function: parserOnHeaders],
onHeadersComplete: [Function: parserOnHeadersComplete],
onBody: [Function: parserOnBody],
onMessageComplete: [Function: parserOnMessageComplete],
socket: [Circular],
incoming: [Circular],
maxHeaderPairs: 2000,
onIncoming: [Function]
},
ondata: [Function],
onend: [Function],
_httpMessage: {output: [],
outputEncodings: [],
writable: true, _last: false, chunkedEncoding: false, shouldKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: true, _hasBody: true, _trailer: '', finished: false,socket: [Circular],
connection: [Circular],
_events: [Object]
}
},
connection: { _handle: {writeQueueSize: 0,
owner: [Circular],
onread: [Function: onread]
},
_pendingWriteReqs: 0,
_flags: 0,
_connectQueueSize: 0,
destroyed: false, errorEmitted: false,bytesRead: 602,
_bytesDispatched: 0,
allowHalfOpen: true, writable: true, readable: true, _paused: false, server: {_connections: 1,
connections: [Getter / Setter],
allowHalfOpen: true,_handle: [Object],
_events: [Object],
httpAllowHalfOpen: false, _connectionKey: '4:0.0.0.0:8124'},
_events: {drain: [Function: ondrain],
timeout: [Object],
error: [Function],
close: [Object]
},
_idleTimeout: 120000,
_idleNext: {_idleNext: [Circular],
_idlePrev: [Circular],
ontimeout: [Function]
},
_idlePrev: {_idleNext: [Circular],
_idlePrev: [Circular],
ontimeout: [Function]
},
_idleStart: Tue Jul 24 2012 01: 18: 39 GMT + 0800(中国标准时间),
parser: {_headers: [],
_url: '',onHeaders: [Function: parserOnHeaders],
onHeadersComplete: [Function: parserOnHeadersComplete],
onBody: [Function: parserOnBody],
onMessageComplete: [Function: parserOnMessageComplete],
socket: [Circular],
incoming: [Circular],
maxHeaderPairs: 2000,
onIncoming: [Function]
},
ondata: [Function],
onend: [Function],
_httpMessage: {output: [],
outputEncodings: [],
writable: true, _last: false, chunkedEncoding: false, shouldKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: true, _hasBody: true, _trailer: '', finished: false,socket: [Circular],
connection: [Circular],
_events: [Object]
}
},
httpVersion: '1.1', complete: true, headers: { accept: 'image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*','accept-language': 'zh-cn',
'user-agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB6; QQDownload 715; .NET CLR 2.0.50727; CIBA; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)',
'accept-encoding': 'gzip, deflate',
host: 'localhost:8124', connection: 'Keep-Alive'},
trailers: {}, readable: false, _paused: false,_pendings: [],
_endEmitted: true, url: '/?callback=abc&abc=1123', method: 'GET', statusCode: null, client: { _handle: {writeQueueSize: 0,
owner: [Circular],
onread: [Function: onread]
},
_pendingWriteReqs: 0,
_flags: 0,
_connectQueueSize: 0,
destroyed: false, errorEmitted: false,bytesRead: 602,
_bytesDispatched: 0,
allowHalfOpen: true, writable: true, readable: true, _paused: false, server: {_connections: 1,
connections: [Getter / Setter],
allowHalfOpen: true,_handle: [Object],
_events: [Object],
httpAllowHalfOpen: false, _connectionKey: '4:0.0.0.0:8124'},
_events: {drain: [Function: ondrain],
timeout: [Object],
error: [Function],
close: [Object]
},
_idleTimeout: 120000,
_idleNext: {_idleNext: [Circular],
_idlePrev: [Circular],
ontimeout: [Function]
},
_idlePrev: {_idleNext: [Circular],
_idlePrev: [Circular],
ontimeout: [Function]
},
_idleStart: Tue Jul 24 2012 01: 18: 39 GMT + 0800(中国标准时间),
parser: {_headers: [],
_url: '',onHeaders: [Function: parserOnHeaders],
onHeadersComplete: [Function: parserOnHeadersComplete],
onBody: [Function: parserOnBody],
onMessageComplete: [Function: parserOnMessageComplete],
socket: [Circular],
incoming: [Circular],
maxHeaderPairs: 2000,
onIncoming: [Function]
},
ondata: [Function],
onend: [Function],
_httpMessage: {output: [],
outputEncodings: [],
writable: true, _last: false, chunkedEncoding: false, shouldKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: true, _hasBody: true, _trailer: '', finished: false,socket: [Circular],
connection: [Circular],
_events: [Object]
}
},
httpVersionMajor: 1,
httpVersionMinor: 1,
upgrade: false}
参考:

浙公网安备 33010602011771号