基于事件驱动的前端通信框架(封装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制作的口袋妖怪游戏(默认小屏下已隐藏,请切换到大分辨率查看).左边是游戏画面,右边是按键表和聊天室.画面达到红蓝版 ...
随机推荐
- unordered_map 与 map 的对比(转)
unordered_map和map类似,都是存储的key-value的值,可以通过key快速索引到value.不同的是unordered_map不会根据key的大小进行排序, 存储时是根据key的ha ...
- Ant 风格路径表达式
ANT通配符有三种: 通配符 说明 ? 匹配任何单字符 * 匹配0或者任意数量的字符 ** 匹配0或者更多的目录 例子: URL路径 说明 /app/*.x 匹配(Matches)所有在app路径下的 ...
- 定制一个类似地址选择器的view
代码地址如下:http://www.demodashi.com/demo/12832.html 前言: 这几天也是闲来无事,看看有什么和Scroller相关的控件需要巩固下,原因很简单,前几天看到相关 ...
- Android API Guides---RenderScript
RenderScript RenderScript是在Android上的高性能执行计算密集型任务的框架. RenderScript主要面向与数据并行计算的使用.尽管串行计算密集型工作负载能够受益.该R ...
- myeclipse svn安装
安装subclipse, SVN 插件 1.从官网下载site-1.6.9.zip文件,网址是:subclipse.tigris.org, 2.从中解压出features与plugins文件夹,复制到 ...
- 支付宝开放平台 配置RSA(SHA1)密钥 OpenSSL配置公钥私钥对
进入到第一次配置支付宝支付服务了 配置支付宝服务,需要去支付宝的开放平台申请服务 需要设置一些参数 其中需要在后台设置配置RSA(SHA1)密钥(公钥(注意这个子读"yao")) ...
- 在oracle11g中配置多个DataGuard物理备机
>> from zhuhaiqing.info 主机配置 alter system set DB_UNIQUE_NAME='starboss' scope=spfile; alter sy ...
- 机器学习11—Apriori学习笔记
votesmart下载 https://pypi.python.org/pypi/py-votesmart test11.py #-*- coding:utf-8 import sys sys.pa ...
- 【Mysql】Navicat For Mysql快捷键
ctrl+q 打开查询窗口ctrl+/ 注释sql语句ctrl+shift +/ 解除注释ctrl+r 运行查询窗口的sql语句ctrl+shift+r 只运行选中的sql语句F6 打开一个mysql ...
- 在express项目中使用redis
在express项目中使用redis 准备工作 安装redis 安装redis桌面管理工具:Redis Desktop Manager 项目中安装redis:npm install redis 开始使 ...