• 使用 Node.JS 構建 Long Polling 應用程序

    1
    JavaScript Java HTML JSON C/C++ 15242 次瀏覽

    Comet是指基于HTTP長連接的“服務器推”技術,是一種新的web應用架構。基于這種架構開發的應用中,服務器端會主動以異步的方式向客戶端程序推送數據,而不需要客戶端顯示的發出請求。非常適合股票交易行情,聊天室等交互性和實時性要求很強的應用。

    長輪詢(Long Polling)是Comet的一種實現方式,也是Facebook,Plurk實現動態更新內容的方法,具體原理是發送一個長時間等待的request,當服務器有資料response的時候立刻斷掉,接著再發送一個新的request。

    我們這里使用新浪微博的openAPI做我們的數據來源,我們需要每隔5秒中推送5條最新的微博內容到客戶端,由客戶端進行呈現。

    我們先來看下前端部分的代碼,這里使用YUI3作為基礎框架。

    <script type="text/javascript">
    YUI().use('jsonp','node-base',function(Y){
    	var handler = function(response){
    		var s = '';
    			for(var i=0;i<response.length;i++){
    				s +='<li class="MIB_linedot_1">';
    				s +='<div class="head_pic"><img src="'+response[i].user.profile_image_url+'"></div>';
    				s +='<divm class="MIB_feed_c"><p class="sms"><a href="#">'+response[i].user.name+'</a> : '+response[i].text+'</p></div>'
    				s +='</li>';
    			}
    			Y.one('#weibo').prepend(s);
    			Y.jsonp('http://127.0.0.1:8000/stream?callback={callback}',arguments.callee);
    		};
    		Y.jsonp('http://127.0.0.1:8000/stream?callback={callback}',handler);
    	});
    </script>

    我們看到在瀏覽器端我們使用JSONP的方式來取得服務器端的數據并執行回調,每次收到服務器端的數據并處理后會再次發起一個JSONP的請求來保持與服務器端的連接。

    下面我們看下服務器端的代碼是怎么樣的,這里不在講述Node.JS的基礎問題,有問題的同學可以去http://nodejs.org查看相關文檔和介紹。

    首先需要引入Node.JS的相關API

    var http = require('http');
    var path = require('path');
    var qs = require('querystring');
    var fs = require('fs');
    var url = require('url');
    接下來我們要創建一個客戶端請求來請求微博openAPI的接口數據。
    var weibo_client = http.createClient(80,'api.t.sina.com.cn');
    然后創建http服務,發送內容到客戶端。
    var server = http.createServer(function(request,response){
    	var uri = url.parse(request.url).pathname;
    	var callback = qs.parse(url.parse(request.url).query).callback;
    	console.log(callback);
    	if(uri === '/stream'){
    	//定時從api得到需要的數據
    	setTimeout(function(){
    		var client_request = weibo_client.request('GET','/statuses/public_timeline.json?source=3364481477&count=5',{'host':'api.t.sina.com.cn'});
    		//對返回的數據進行處理
    		client_request.on('response',function(res){
    			var body = '';
    			res.on('data',function(data){
    				body += data;
    			});
    
    			res.on("end",function(){
    				var weibo = JSON.parse(body);
    				if(weibo.length > 0){
    					response.writeHead(200,{'Content-Type':'text/javasript'});
    					var text = callback + "("+JSON.stringify(weibo)+")";
    					console.log(text);
    					response.write(text);
    					response.end();
    				}
    			});
    		});
    		client_request.end();
    	},5000);
    	}else{
    		load_static_file(uri,response);
    	}
    });

    在上面的代碼中當客戶端連接到服務器端請求數據的時候,我們就每隔5秒去請求一次openAPI的接口,獲取到最新的5條feed信息,通過監聽 clientRequest的response事件來獲得最新的數據。通過監聽clientRequest的end事件對獲得的數據轉換為JSON格式的 字符串并推送到客戶端去。

    最后我們開啟http服務就可以了。

    1 Server.listen(8000);

    下面是該程序的所有代碼:
    客戶端:

    <!DOCTYPE html>
    <html>
    	<head>
    		<title>weibo stream</title>
    		<link  type="text/css" rel="stylesheet" />
    		<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js"></script>
    	</head>
    	<body>
    		<ul id="weibo" class="MIB_feed" style="width:555px;"></ul>
    		<script type="text/javascript">
    		YUI().use('jsonp','node-base',function(Y){
    			var handler = function(response){
    			console.log(response);
    			var s = '';
    			for(var i=0;i<response.length;i++){
    				s +='<li class="MIB_linedot_1">';
    				s +='<div class="head_pic"><img src="'+response[i].user.profile_image_url+'"></div>';
    				s +='<divm class="MIB_feed_c"><p class="sms"><a href="#">'+response[i].user.name+'</a> : '+response[i].text+'</p></div>'
    				s +='</li>';
    			}
    			Y.one('#weibo').prepend(s);
    			Y.jsonp('http://127.0.0.1:8000/stream?callback={callback}',arguments.callee);
    			};
    			Y.jsonp('http://127.0.0.1:8000/stream?callback={callback}',handler);
    		});
    		</script>
    	</body>
    </html>
    Server:
    var http = require('http');
    var path = require('path');
    var qs = require('querystring');
    var fs = require('fs');
    var url = require('url');
    
    //創建http client服務
    var weibo_client = http.createClient(80,'api.t.sina.com.cn');
    
    //讀取靜態文件
    var load_static_file = function(uri,response){
    	var filename = path.join(process.cwd(),uri);
    	path.exists(filename,function(exists){
    		if(!exists){
    			response.writeHeader(404,{'Content-Type':'text/plain'});
    			response.write('404 Not Found\n');
    			response.end();
    			return;
    		}
    
    		fs.readFile(filename,'binary',function(err,file){
    			if(err){
    				response.writeHeader(500,{'Content-Type':'text/plain'});
    				response.write(err + '\n');
    				response.end();
    				return;
    			}
    
    			response.writeHeader(200);
    			response.write(file,'binary');
    			response.end();
    		});
    	});
    };
    
    //創建http服務
    var server = http.createServer(function(request,response){
    	var uri = url.parse(request.url).pathname;
    	var callback = qs.parse(url.parse(request.url).query).callback;
    	console.log(callback);
    	if(uri === '/stream'){
    	//定時從api得到需要的數據
    	setTimeout(function(){
    		var client_request = weibo_client.request('GET','/statuses/public_timeline.json?source=3364481477&count=5',{'host':'api.t.sina.com.cn'});
    		//對返回的數據進行處理
    		client_request.on('response',function(res){
    			var body = '';
    			res.on('data',function(data){
    				body += data;
    			});
    
    			res.on("end",function(){
    				var weibo = JSON.parse(body);
    				if(weibo.length > 0){
    					response.writeHead(200,{'Content-Type':'text/javasript'});
    					var text = callback + "("+JSON.stringify(weibo)+")";
    					console.log(text);
    					response.write(text);
    					response.end();
    				}
    			});
    		});
    		client_request.end();
    	},5000);
    	}else{
    		load_static_file(uri,response);
    	}
    });
    
    server.listen(8000);

    該程序在Node.JS v0.4.6版本下測試通過。

    原文出處:http://ued.sina.com/?p=801

    相似問題

    相關經驗

    相關資訊

    相關文檔

  • sesese色