UNPKG

remote_event

Version:

Event System Based on ZMQ

223 lines (195 loc) 6.05 kB
/** * Created with JetBrains WebStorm. * User: aishen * Date: 13-9-22 * Time: 下午7:58 * To change this template use File | Settings | File Templates. * * Client For REvent */ var zmq = require('zmq'); var RPC_TIMEOUT_DEFAULT = 5000; /** * * @param host REventServer所处host地址 * @param listenPort REventServer监听client请求的端口 * @param publishPort REventServer发布事件通知的端口 * @constructor */ var REventClient = function(host, listenPort, publishPort){ this.host = host; this.listenPort = listenPort; this.publishPort = publishPort; this.listenRemote = [ "tcp://", this.host, ':', this.listenPort ].join(''); this.publishRemote = [ "tcp://", this.host, ':', this.publishPort ].join(''); this._init_(); } REventClient.prototype._init_ = function(){ this.notifySocket = zmq.socket('req'); this.observerSocket = zmq.socket('sub'); this.notifySocket.connect(this.listenRemote); this.observerSocket.connect(this.publishRemote); var self = this; this.observerSocket.on('message', function(data){ var dataStr = data.toString().replace(/^ */, ''); var index = dataStr.indexOf(' '); var event = dataStr.slice(0, index); var param = dataStr.slice(index + 1); self.onEvent(event, param); }); this.eventMap = {}; this.rpcMap = {}; this.rpcCount = 0; } /** * 添加一个事件监听 * @param event 事件名称 * @param callback 事件回调函数 */ REventClient.prototype.addObserver = function(event, callback){ var socket = this.observerSocket; var observers = this.eventMap[event]; if(observers && observers.length > 0){ if( callback in observers ){ ; }else{ observers.push(callback); } }else{ socket.subscribe(event); this.eventMap[event] = new Array(); this.eventMap[event].push(callback); } } /** * 移除一个事件的监听函数 * 如果事件的监听函数列表为空,则移除socket的监听 * @param event * @param callback */ REventClient.prototype.removeObserver = function(event, callback){ if(!callback){ this.eventMap[event] && (this.eventMap[event].length = 0); this.observerSocket.unsubscribe(event); return; } var socket = this.observerSocket; var observers = this.eventMap[event]; //移除监听函数 if(observers && observers.length > 0){ for(var i = 0, len = observers.length; i < len; i ++){ if(observers[i] == callback){ observers.splice(i, 1); break; } } } //如果监听函数列表为空,则移除socket的监听 if(observers && ( observers.length = 0 )){ socket.unsubscribe(event); } } /** * 接收到REventServer的事件推送 * @param event * @param param */ REventClient.prototype.onEvent = function(event, param){ //console.log('onEvent:', event, param); //console.log(this.eventMap); var observers = this.eventMap[event]; if(observers && observers.length > 0){ for(var i = 0, len = observers.length; i < len; i ++){ var observer = observers[i]; observer(param); } } } /** * client对server的事件通知 * @param event * @param param */ REventClient.prototype.notifyObservers = function(event, param){ var socket = this.notifySocket; socket.send(JSON.stringify({ event: event, param: param })); } /** * client 进行一次rpc调用 * rpcRoute rpc的调用route * param * callback rpc调用的回调函数 */ REventClient.prototype.rpc = function(){ var argLength = arguments.length; if(argLength < 1){ return; } var rpcRoute = arguments[0]; var callback = argLength > 1 ? arguments[ argLength - 1 ]: function(){} var paramList = []; for(var i = 1; i < argLength - 1; i ++){ paramList.push(arguments[i]); } var id = this.rpcCount ++; var self = this; var rpcItem = { id : id, callback : callback, timeout : setTimeout(function(){ callback(new Error('rpc call '+ id + ' timeout')); self._resetRpc(id); }, RPC_TIMEOUT_DEFAULT), rpcCallbckRoute : this._getRouteById(id) } this.rpcMap[id] = rpcItem; paramList.push(id); this.addObserver(rpcItem.rpcCallbckRoute, function(data){ callback && callback(null, data); self._resetRpc(id); }); this.notifyObservers(rpcRoute, paramList); } REventClient.prototype._resetRpc = function(id){ var ipcItem = this.rpcMap[id]; if(ipcItem){ clearTimeout(ipcItem.timeout); this.removeObserver(ipcItem.rpcCallbckRoute, null); ipcItem = null; delete this.rpcMap[id]; } } REventClient.prototype._getRouteById = function(id){ return [id, "rpcRoute", "callback"].join('-'); } /** * 注册rpc服务 * @param rpcRoute rpc调用时的route * @param handler rpc的处理函数 * handler = function(rpcParam, callback){} * handler接受两个参数: rpcParam表示调用参数, * rpc服务的处理结果传递给callback */ REventClient.prototype.registerRpc = function(rpcRoute, handler){ var self = this; /** * rpcParam { event: '', param: '' } */ this.addObserver(rpcRoute, function(rpcParam){ rpcParam = typeof rpcParam == "string" ? JSON.parse(rpcParam) : rpcParam; var id = rpcParam.pop(); var callback = function(id, data){ var route = self._getRouteById(id); self.notifyObservers(route, data); } callback = callback.bind(null, id); handler.apply(null, rpcParam.concat(callback)); }); } REventClient.prototype.unRegisterRpc = function(rpcRoute, callback){ this.removeObserver(rpcRoute, callback); } module.exports = REventClient;