; (function (root, factory) {
var ws = factory(root);
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof module !== 'undefined' && module.exports) {
module.exports = factory();
} else {
root.ws = factory();
}
}(this, function (root, undefined) {
if (!('WebSocket' in window)) return;
var _handlers = {}, wsocket,
eventTarget = document.createElement('div'),
settings = {
//是否自动重连
automaticOpen: true,
//自动重连延迟重连速度速度
reconnectDecay: 1.5
},
func = function () { },
//对外泄露 API 😄
_api = {
CONNECTING: WebSocket.CONNECTING,
OPEN: WebSocket.OPEN,
CLOSING: WebSocket.CLOSING,
CLOSED: WebSocket.CLOSED
};
/**
* [ws]
* @param 参数 url 为建立连接的URL
* @param 参数 protocols 为服务器选择的子协定
* @param 参数 options 初始化定义参数
*/
function ws(url, protocols, options) {
var self = this;
//websocket url
this.url = url;
//websocket 状态
this.readyState = WebSocket.CONNECTING;
/**
* 服务器选择的子协定,这是建立 WebSocket 对象时 protocols 参数里的其中一个字符串。
*/
this.protocol = protocols ? protocols : null;
// 绑定选项定义设置
if (!options) { options = {}; }
for (var key in settings) {
if (typeof options[key] !== 'undefined') this[key] = options[key];
else this[key] = settings[key];
}
// 公开 API
for (var a in _api) this[a] = _api[a];
//用事件处理程序
eventTarget.addEventListener('open', function (event) { self !== window && self.onopen(event); });
eventTarget.addEventListener('close', function (event) { self !== window && self.onclose(event); });
eventTarget.addEventListener('connecting', function (event) { self !== window && self.onconnecting(event); });
eventTarget.addEventListener('message', function (event) { self !== window && self.onmessage(event); });
eventTarget.addEventListener('error', function (event) { self !== window && self.onerror(event); });
// 公开事件目标的API
this.addEventListener = eventTarget.addEventListener.bind(eventTarget);
this.removeEventListener = eventTarget.removeEventListener.bind(eventTarget);
this.dispatchEvent = eventTarget.dispatchEvent.bind(eventTarget);
if (this.automaticOpen === true && this !== window) this.open();
return this;
}
/**
* [generateEvent 该函数产生一个事件,与标准兼容,兼容的浏览器和IE9 - IE11?]
* http://stackoverflow.com/questions/19345392/why-arent-my-parameters-getting-passed-through-to-a-dispatched-event/19345563#19345563
* https://msdn.microsoft.com/library/ff975299(v=vs.85).aspx
* @param eventName 位字符串类型的事件名字
* @param 参数的args对象的可选对象,该事件将使用
*/
function generateEvent(eventName, args) {
var evt = document.createEvent("CustomEvent");
evt.initCustomEvent(eventName, false, false, args);
return evt;
}
ws.prototype.onconnecting = func;
ws.prototype.onerror = func;
ws.prototype.onopen = func;
ws.prototype.onmessage = func;
/**
* [send 发送 websocket 消息]
* @param 参数 data 为发消息的内容
*/
ws.prototype.send = function (data) {
if (this.wsocket) this.wsocket.send(data);
else {
throw 'INVALID_STATE_ERR : Pausing to reconnect websocket';
}
};
ws.prototype.invoke=function(action, args, callback) {
var msg = { action: action, args: args };
if (this.wsocket) this.wsocket.send(JSON.stringify(msg));
else {
throw 'INVALID_STATE_ERR : Pausing to reconnect websocket';
}
}
/**
* [close 关闭 websocket 连接。]
* 如果已经关闭了连接,此方法不起作用。
*
* 错误代码参考:https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
* @param 参数 code 为错误代码 1000为正常关闭
* @param 参数 reason 为错误理由
*/
ws.prototype.close = function (code, reason) {
// 默认CLOSE_NORMAL代码
if (typeof code === 'undefined') code = 1000;
if (this.wsocket) this.wsocket.close(code, reason);
};
/**
* [open 打开建立 websocket 握手连接]
*/
ws.prototype.open = function () {
var self = this;
wsocket = new WebSocket(this.url, this.protocol || []);
eventTarget.dispatchEvent(generateEvent('connecting'));
wsocket.onopen = function (event) {
self.protocol = ws.protocol;
self.readyState = WebSocket.OPEN;
var e = generateEvent('open');
eventTarget.dispatchEvent(e);
};
wsocket.onclose = function (event) {
self.readyState = WebSocket.CLOSED;
var e = generateEvent('connecting');
e.code = event.code;
e.reason = event.reason;
e.wasClean = event.wasClean;
eventTarget.dispatchEvent(e);
eventTarget.dispatchEvent(generateEvent('close'));
};
wsocket.onmessage = function (event) {
var e = generateEvent('message');
e.data = event.data;
eventTarget.dispatchEvent(e);
};
wsocket.onerror = function (event) {
var e = generateEvent('error');
eventTarget.dispatchEvent(e);
};
this.wsocket = wsocket;
return this;
};
return ws;
}));
|