基于事件驱动的前端通信框架(封装socket.io)
socket.io的使用可以很轻松的实现websockets,兼容所有浏览器,提供实时的用户体验,并且为程序员提供客户端与服务端一致的编程体验。但是在使用socket.io的过程中,由于业务需求需要同时发起几个请求,并等待数据返回调用相对应的回调函数执行,那么在数据返回时,你如何知道这个数据是要用于那个回调函数的,也就是说该去执行那个回调函数来处理返回来的数据?在使用AS过程中发现,AS的事件机制是一个很灵活的东西,你可以自定义多个事件监听,然后在派发事件的时候会根据你派发的事件调用相对应的回调函数。那么如何把这一东西用到socket.io中呢,就是如果发送某个请求时同事让它与它需要回调的函数关联,那么在请求返回数据的时候我就可以根据这个关联找到它要回调的函数并执行。就像AS的事件机制一样,你为某个事件添加了监听,那么当这个事件派发出来的时候就会去调用相对应的回调函数。为了实现这一目的我做了以下几个东西。
首先是Event类:
/**
* 事件类
*/
var Event = function (type, data,cancelable) {
this.cancelable = cancelable; //是否取消传递
this.type = type; //类型
this.data = data; // 数据 /// <summary>
/// 复制
/// </summary>
/// <returns type="Event">复制后的元素</returns>
this.clone = function() {
var that = new Event();
that.cancelable = this.cancelable;
that.type = this.type;
that.data = this.data;
return that;
}; this.toString = function() {
return "Event( type: " + this.type + ", cancelable: " + this.cancelable + this.eventPhase + ")";
};
};
接着是EventListener :
/**
* 事件监听类
* @param listener 监听回调函数
* @param priority 优先级
*/
var EventListener = function (listener,priority) {
if (typeof(arguments[0]) != "function") {
throw new Error("必须指明listener");
}
this.listener = listener;
this.priority = priority?priority:0;
};
再接着是EventManager,用于关联事件和它对应的回调 :
var EventManager = {
eventListeners : [],
/// <summary>
/// 添加事件处理函数
/// </summary>
/// <param name="type">类型</param>
/// <param name="listener">处理函数</param>
/// <param name="priority">优先级,默认为0</param>
addEventListener : function (type, listener, priority) {
if (typeof (arguments[1]) != "function") {
throw new Error("必须指明type和listener");
}
if (!this.eventListeners[type]) {
this.eventListeners[type] = [];
}
var index = this.eventListeners[type].length;
console.log(type + "监听个数:" + index);
//防止重复监听
for (var i = 0; i < index; i++) {
var temp = this.eventListeners[type][i];
if (temp.listener == listener) {
return;
}
}
var eventListener = new EventListener(listener, priority);
this.eventListeners[type].push(eventListener);
this.eventListeners[type].sort(function (a, b) { return a.priority - b.priority; });
},
/// <summary>
/// 移除监听器
/// </summary>
/// <param name="type">类型</param>
/// <param name="listener">监听器</param>
removeEventListener : function (type, listener) {
var len = arguments.length;
if (len < 2) {
throw new Error("必须指定type 与 listener");
}
if (!this.eventListeners[type]) {
return;
}
var index = this.eventListeners[type].length;
//如果数组长度为0,删掉整个数组
if (index == 0) {
var lisIndex = this.eventListeners.length;
for (var i = 0; i < lisIndex; i++) {
if (type == this.eventListeners[i]) {
this.eventListeners.splice(i, 1);
}
}
} else {
for (var j = 0; j < index; j++) {
var temp = this.eventListeners[type][0];
if (temp.listener == listener) {
this.eventListeners[type].splice(0, 1);
}
}
}
},
/// <summary>
/// 分派一个事件
/// </summary>
/// <param name="event">事件</param>
dispatchEvent : function (event) {
// 如果event不是一个Event类,则默认是字符串,作为事件标识创建一个新的Event(event)
event = (typeof (event) == "string") ? new Event(event) : event;
if (!this.eventListeners[event.type]) {
return;
}
var index = this.eventListeners[event.type].length;
for (var k = 0; k < index; k++) {
var temp = this.eventListeners[event.type][k];
if (temp.listener) {
if (!event.cancelable) {
temp.listener(event);
} else {
continue;
}
}
}
},
/// <summary>
/// 判断是否具有该事件的处理器
/// </summary>
/// <param name="type">事件类型</param>
/// <returns type="boolean">判断是否具有该事件的处理器</returns>
hasEventListener : function (type) {
return this.eventListeners[type] && this.eventListeners[type].length > 0;
}
};
接着是各个不同的数据请求,例如增删改查命令
var RequestManager = {
sendData: function (eventType, params, listener, priority) {
EventManager.addEventListener(eventType, listener, priority);
console.log("发包,事件:" + eventType);
var json = {
eventType: eventType,
parameters: params
};
SocketManager._instance.json.send(json);
},
readData: function (data) {
var evt = new Event();
evt.type = data.eventType;
evt.data = data;
EventManager.dispatchEvent(evt);
}
};
再来是SocketManager,对socket.io进行封装,这里相当于是单例的实现,保证了应用中只存在一个socket:
var SocketManager = {
_instance: null,
connect: function (ip,port) {
if (_instance) {
return;
}
_instance = io.connect("http://" + ip + ":" + port);
_instance.on("connect", function (data) {
console.log("Connected to Server");
});
_instance.on("message", function (data) {
console.log("readData:" + data);
RequestManager.readData(data);
});
_instance.on('reconnect', function () {
console.log("reconnect to Server");
});
}
};
使用起来也非常简单,通过调用SocketManager.connect(ip,port);即可实例化一个socket,再来通过RequestManager.sendData("getData1", params, getData1Handler, 0);既可完成数据访问,但同时有很多个请求时,如RequestManager.sendData("getData2", params, getData2Handler, 1);RequestManager.sendData("getData3", params, getData3Handler, 2);同样可以根据数据的eventType类型调用对应的回调函数。
基于事件驱动的前端通信框架(封装socket.io)的更多相关文章
- 即时通信WebSocket 和Socket.IO
WebSocket HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯. 在2008年诞生,2011年成为国际标准. 现在基本所有浏览器都已经支持了. We ...
- 艺萌文件上传下载及自动更新系统(基于networkComms开源TCP通信框架)
1.艺萌文件上传下载及自动更新系统,基于Winform技术,采用CS架构,开发工具为vs2010,.net2.0版本(可以很容易升级为3.5和4.0版本)开发语言c#. 本系统主要帮助客户学习基于TC ...
- 搭建简易的WebServer(基于pyhton实现简易Web框架 使用socket套接字)
1. 使用web底层socket的方式实现简易服务器的搭建,用来理解学习 # 1.导入socket模块 import socket import re import gevent import sys ...
- 基于 nodejs 的 webSockt (socket.io)
基于 nodejs 的 webSockt (socket.io) 理解 本文的业务基础是在基于 nodejs 的 socket.io 的直播间聊天室(IM)应用来的. 项目中具体的 框架如下 expr ...
- 基于socket.io的实时消息推送
用户访问Web站点的过程是基于HTTP协议的,而HTTP协议的工作模式是:请求-响应,客户端发出访问请求,服务器端以资源数据响应请求. 也就是说,服务器端始终是被动的,即使服务器端的资源数据发生变化, ...
- twisted是python实现的基于事件驱动的异步网络通信构架。
网:https://twistedmatrix.com/trac/ http://www.cnblogs.com/wy-wangyan/p/5252271.html What is Twisted? ...
- 前端通信:ajax设计方案(八)--- 设计请求池,复用请求,让前端通信快、更快、再快一点
直接进入主题,本篇文章有点长,包括从设计阶段,到摸索阶段,再到实现阶段,最后全面覆盖测试阶段(包括数据搜集清洗),还有与主流前端通信框架进行对比PK阶段. 首先介绍一下一些概念: 1. 浏览器的并发能 ...
- 基于React 的前端UI开发框架 及与Electron 的结合 https://cxjs.io/
1.cxjs 基于React 的前端UI开发框架 https://cxjs.io/ coreu http://coreui.io/ 2.antd-admin ...
- Socket.io:有点意思
个人网站 欢迎品尝 edwardesire.com 下面页面就是使用Socket.io制作的口袋妖怪游戏(默认小屏下已隐藏,请切换到大分辨率查看).左边是游戏画面,右边是按键表和聊天室.画面达到红蓝版 ...
随机推荐
- 【Django】01_创建一个简单的项目
1.创建Django项目 点击:file-->new project,出现下面的对话框.选择Django栏目,输入项目名称, 选择python解释器版本,点击create创建. Django将自 ...
- SQLserver备份数据库示例
BACKUP DATABASE [yee]TO DISK = N'D:\数据库备份\yee2015.9.11.bak'WITH NAME = N'yee - 备份', NOFORMAT, NO ...
- Gradle学习小结
build.gradle(依赖配置) // 普通java工程 apply plugin: 'java' // Idea工程 apply plugin: 'idea' // war工程,需要有webap ...
- Struts2学习小结
1 基础 使用:导入 jar 包,配置 web.xml,并引入 struts.xml 文件 DMI:动态方法调用,调用时使用!分隔 action 名与方法名,如 index ! add.action, ...
- UITableViewCell中的UILabel添加手势没有响应的解决方法
有时候自定义UITableViewCell,且cell中添加了一个UILabel,我们的目的是给该label添加一个手势.但是如果按照常规的添加方法,发现所添加的手势并不能响应.以下为解决方法:将手势 ...
- 操作符(运算符)重载 或者叫 二元运算符 operator + 与 转换式操作符 implicit operator explicit operator
static void Main(string[] args) { rational r1 = new rational(5); rational r2 = new rational(51); rat ...
- elasticsearch 单节点实现
一.安装java环境,这么不说了,一般用源码安装,配置好环境变量 二.新建es用户和组,es不能用root启动 三.下载需要的稳定版es 四.解压安装es .zip /opt/app/ es / 五. ...
- JS input 银行卡号格式转换
replace(/\D/g,'').replace(/....(?!$)/g,'$& ')
- poj 2367
Genealogical tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3658 Accepted: 2433 ...
- 刨根问底 HTTP 和 WebSocket 协议(上)
HTTP vs WebSocket 那天和boss聊天,不经意间提到了Meteor,然后聊到了WebSocket,然后就有了以下对话,不得不说,看问题的方式不同,看到的东西也会大不相同. A:Mete ...