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)的更多相关文章

  1. 即时通信WebSocket 和Socket.IO

    WebSocket HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯. 在2008年诞生,2011年成为国际标准. 现在基本所有浏览器都已经支持了. We ...

  2. 艺萌文件上传下载及自动更新系统(基于networkComms开源TCP通信框架)

    1.艺萌文件上传下载及自动更新系统,基于Winform技术,采用CS架构,开发工具为vs2010,.net2.0版本(可以很容易升级为3.5和4.0版本)开发语言c#. 本系统主要帮助客户学习基于TC ...

  3. 搭建简易的WebServer(基于pyhton实现简易Web框架 使用socket套接字)

    1. 使用web底层socket的方式实现简易服务器的搭建,用来理解学习 # 1.导入socket模块 import socket import re import gevent import sys ...

  4. 基于 nodejs 的 webSockt (socket.io)

    基于 nodejs 的 webSockt (socket.io) 理解 本文的业务基础是在基于 nodejs 的 socket.io 的直播间聊天室(IM)应用来的. 项目中具体的 框架如下 expr ...

  5. 基于socket.io的实时消息推送

    用户访问Web站点的过程是基于HTTP协议的,而HTTP协议的工作模式是:请求-响应,客户端发出访问请求,服务器端以资源数据响应请求. 也就是说,服务器端始终是被动的,即使服务器端的资源数据发生变化, ...

  6. twisted是python实现的基于事件驱动的异步网络通信构架。

    网:https://twistedmatrix.com/trac/ http://www.cnblogs.com/wy-wangyan/p/5252271.html What is Twisted? ...

  7. 前端通信:ajax设计方案(八)--- 设计请求池,复用请求,让前端通信快、更快、再快一点

    直接进入主题,本篇文章有点长,包括从设计阶段,到摸索阶段,再到实现阶段,最后全面覆盖测试阶段(包括数据搜集清洗),还有与主流前端通信框架进行对比PK阶段. 首先介绍一下一些概念: 1. 浏览器的并发能 ...

  8. 基于React 的前端UI开发框架 及与Electron 的结合 https://cxjs.io/

    1.cxjs  基于React 的前端UI开发框架    https://cxjs.io/ coreu   http://coreui.io/ 2.antd-admin                ...

  9. Socket.io:有点意思

    个人网站 欢迎品尝 edwardesire.com 下面页面就是使用Socket.io制作的口袋妖怪游戏(默认小屏下已隐藏,请切换到大分辨率查看).左边是游戏画面,右边是按键表和聊天室.画面达到红蓝版 ...

随机推荐

  1. mobx 小结

    1.@observable 是一种让数据的变化可以被观察的方法 //@observable data 注册一个数据,这个数据将会成为一个可mobx监测的数据 2.decorator 修饰器只能修饰 类 ...

  2. 【Excle数据透视】如何隐藏数据透视表字段的分类汇总

    如下图:是显示数据透视表的分类汇总 那么我们现在想弄成以下这样,不显示分类汇总 如何操作呢? 步骤 单击数据透视表任意单元格→数据透视表工具→设计→分类汇总→不显示分类汇总 ***显示分类汇总*** ...

  3. 【VBA】隐藏正在使用的工作簿

    正在使用的工作簿,嫌窗口太多,不利于操作,想把窗口隐藏,该怎么做呢? Public Sub 隐藏正在使用的工作簿() Application.Visible = False MsgBox " ...

  4. http://www.bootcss.com/p/font-awesome/design.html

    http://www.bootcss.com/p/font-awesome/design.html <li class="active"> <div class= ...

  5. ASP.NET CORE RAZOR :将搜索添加到 Razor 页面应用

    https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/razor-pages/search 本文档中,将向索引页面添加搜索功能以实现按“流派”或 ...

  6. 解决:cant&#39;t run &#39;/etc/init.d/rcS&#39;:No such file or directory

    Linux内核启动时提示这种错误:cant't run '/etc/init.d/rcS':No such file or directory 请用vim打开文件:/etc/init.d/rcS 观察 ...

  7. mac权限

    mac文件后面出现@权限 去除方法: xattr -c 文件名  目录也可以

  8. 教你用squid做CDN把公司做到上市

    我们都知道CDN(内容分发网络)是用来给网站加速用的,通过在现有的Internet中增加一层新的网络架构,将网站的内容发布到最接近用户的网络的“边缘”,使用户可以就近取得所需的内容,以提高用户访问网站 ...

  9. CSS 温故而知新 断句失败

    设置了一定的宽度和高度.但无论是下面哪句都无效. word-break: break-word; word-wrap: break-word; 原因竟然是因为 /* white-space: nowr ...

  10. 涛哥的Python脚本工具箱之生成带Logo的二维码

    近期须要在二维码上加Logo,网上没有找到好用的,于是自己用python写了一个. 须要安装qrcode,PIL库 二维码简称 QR Code(Quick Response Code),学名为高速响应 ...