在作商品拍賣的時候,要求在商品的拍賣頁面須要實時的更新當前商品的最高價格。實現的方式有不少,好比:php
1.setInterval每隔n秒去異步拉取數據(缺點:更新不夠實時)html
2. AJAX輪詢方式方式推送數據(缺點:服務端須要在死循環中反覆查詢數據庫)html5
3.websocket推送數據(缺點:僅支持html5標準的瀏覽器)node
socket.io的簡要介紹web
全部客戶端都經過socket.io掛在nodejs服務器上(注意: 只是掛着,不須要任何循環,由於它是事件驅動的);須要推送消息了,服務器就與nodejs通訊(好比訪問某個地址來實現),告訴它推送什麼消息到哪裏;nodejs收到推送信號後,則經過socket.io實時傳輸數據給瀏覽器。這個其實也是一條單向的路,由於nodejs服務器不具有與php通訊的能力,實際上也不須要,網頁上直接連php就能夠了。redis
接下來開始整理下思路數據庫
1.正如簡要介紹中所說的首先要將客戶端都經過socket.io掛在nodejs服務器上.express
在用戶進入拍賣頁面後開始鏈接socket.io ,而後將當前客戶端的'用戶id','拍賣id','當前最高價','socket.id'存儲至node.js全局變量socketUser中.瀏覽器
//客戶端緩存
var socket = io.connect("http://demo.xiaocai.name":339");
socket.on('conn', function (data) {
var postdata = {
'c_id' : PageValue.charinfo.c_id, //用戶id
'c_name' : PageValue.charinfo.c_name, //用戶暱稱
'guid' : PageValue.infodata.id,//拍賣id
'price' : PageValue.infodata.max_price,//當前最高價
}
socket.emit('login', postdata,function(result){
console.log('登錄成功');
});
});
//服務端
var sio = require('socket.io');
var express = require('express');
var app = module.export = express.createServer();
//初始化
var socketUser = {};
io = sio.listen(app);
io.set('log level', 1);//將socket.io中的debug信息關閉
//監聽鏈接
io.sockets.on('connection', function (socket){
//響應鏈接
io.sockets.emit('conn', { text: 'socketId:'+socket.id});
//監聽用戶登陸並存儲socket
socket.on('login', function (data,fn) {
socketUser[socket.id] = {'c_id':data.c_id,'guid':data.guid,'price':data.price,'socket':socket};
});
//監聽斷線
socket.on('disconnect', function(){
console.log('-連接斷開['+socket.id+']-');
delete socketUser[socket.id];
});
});
從redis緩存中讀取出當前拍賣的最高價,而後遍歷該拍賣下的socketUser集合,若它的價格低於取出的最高價則向它推送最新的價格(而且更新它的最高價).GetRedisKey是個讀取reids的方法該方法在底部貼出.
var pushprice = function(guid){
console.log('-推送數據['+guid+']-');
common_func.GetRedisKey("AuctionMaxPrice-"+guid,function(val){
if(!val){
return false;
}
for(var values in socketUser){
if( parseFloat(socketUser[values].price) < val && socketUser[values].guid == guid ){
socketUser[values].socket.emit('receive',{'nowprice':val});
socketUser[values].price = val;
}
}
});
}
3.客戶端接受推送的數據
socket.on('receive',function(maxprice){
$('#NowUserTxt').html('¥'+maxprice);
});
GetRedisKey是公共函數中得到redis緩存的方法,這邊單獨貼出來
exports.GetRedisKey = function(key,fun){
if( typeof redis_client == 'undefined' ){
var redis = require("redis");
redis_client = redis.createClient(RedisPort,RedisHost);
redis_client.on("error", function (err) {
common_func.insertlog("Error(redis): " + err);
})
}
redis_client.get(key, function (err, reply) {
if(reply){
fun(reply.toString());
}else{
fun(false);
common_func.insertlog('Error(redis): get('+key+') not data');
}
});
}