var wxTunnel = require('./wxTunnel');
|
|
/**
|
* 当前打开的socket通道,同一时间只能有一个socket通道打开
|
*/
|
var currentSocketTunnel = null;
|
|
// 信道状态枚举
|
var STATUS_CLOSED = SocketTunnel.STATUS_CLOSED = 'CLOSED';
|
var STATUS_CONNECTING = SocketTunnel.STATUS_CONNECTING = 'CONNECTING';
|
var STATUS_ACTIVE = SocketTunnel.STATUS_ACTIVE = 'ACTIVE';
|
|
// 错误类型枚举
|
var ERR_CONNECT_SOCKET = SocketTunnel.ERR_CONNECT_SOCKET = 1002;
|
var ERR_SOCKET_ERROR = SocketTunnel.ERR_SOCKET_ERROR = 3001;
|
|
function SocketTunnel(socketUrl) {
|
if (currentSocketTunnel && currentSocketTunnel.status !== STATUS_CLOSED) {
|
close(false)
|
}
|
|
currentSocketTunnel = this;
|
|
// 等确认微信小程序全面支持 ES6 就不用那么麻烦了
|
var me = this;
|
|
//=========================================================================
|
// 暴露实例状态以及方法
|
//=========================================================================
|
this.socketUrl = socketUrl;
|
this.status = null;
|
|
this.open = openConnect;
|
this.on = registerEventHandler;
|
this.close = close;
|
|
this.isClosed = isClosed;
|
this.isConnecting = isConnecting;
|
this.isActive = isActive;
|
this.send = sendPacket;
|
|
|
//=========================================================================
|
// socket状态处理,状态说明:
|
// closed - 已关闭
|
// connecting - 首次连接
|
// active - 当前socket已经在工作
|
//=========================================================================
|
function isClosed() { return me.status === STATUS_CLOSED; }
|
function isConnecting() { return me.status === STATUS_CONNECTING; }
|
function isActive() { return me.status === STATUS_ACTIVE; }
|
|
function setStatus(status) {
|
var lastStatus = me.status;
|
if (lastStatus !== status) {
|
me.status = status;
|
}
|
}
|
|
// 初始为关闭状态
|
setStatus(STATUS_CLOSED);
|
|
|
//=========================================================================
|
// socket事件处理机制
|
// socket事件包括:
|
// connect - 连接已建立
|
// close - 连接被关闭(包括主动关闭和被动关闭)
|
// error - 发生错误
|
// message - websocket服务器发送过来消息
|
//=========================================================================
|
var preservedEventTypes = 'connect,close,error,message'.split(',');
|
var eventHandlers = [];
|
|
/**
|
* 注册消息处理函数
|
* @param {string} messageType 支持类型("connect"|"close"|"error"|"message")
|
*/
|
function registerEventHandler(eventType, eventHandler) {
|
if (typeof eventHandler === 'function') {
|
eventHandlers.push([eventType, eventHandler]);
|
}
|
}
|
|
/**
|
* 派发事件,通知所有处理函数进行处理
|
*/
|
function dispatchEvent(eventType, eventPayload) {
|
eventHandlers.forEach(function (handler) {
|
var handleType = handler[0];
|
var handleFn = handler[1];
|
|
if (handleType === eventType) {
|
handleFn(eventPayload);
|
}
|
});
|
}
|
|
//=========================================================================
|
// 连接控制
|
//=========================================================================
|
var isOpening = false;
|
|
/**
|
* 进行 WebSocket 连接
|
*/
|
function openConnect() {
|
if (isOpening) return;
|
isOpening = true;
|
setStatus(STATUS_CONNECTING);
|
openSocket(me.socketUrl);
|
}
|
|
/**
|
* 打开 WebSocket 连接,打开后,注册微信的 Socket 处理方法
|
*/
|
function openSocket(url) {
|
wxTunnel.listen({
|
onOpen: handleSocketOpen,
|
onMessage: handleSocketMessage,
|
onClose: handleSocketClose,
|
onError: handleSocketError,
|
});
|
|
wx.connectSocket({ url: url });
|
}
|
|
|
//=========================================================================
|
// 处理消息
|
//=========================================================================
|
|
// 连接还没成功建立的时候,需要发送的包会先存放到队列里
|
var queuedPackets = [];
|
|
/**
|
* WebSocket 打开之后,更新状态,同时发送所有遗留的数据包
|
*/
|
function handleSocketOpen() {
|
/* istanbul ignore else */
|
if (isConnecting()) {
|
dispatchEvent('connect');
|
|
}
|
|
setStatus(STATUS_ACTIVE);
|
}
|
|
/**
|
* 收到 WebSocket 数据包,交给处理函数
|
*/
|
function handleSocketMessage(message) {
|
dispatchEvent('message', message);
|
}
|
|
/**
|
* 数据包推送到websocket
|
*/
|
function sendPacket(packet) {
|
wx.sendSocketMessage({
|
data: packet,
|
fail: handleSocketError,
|
});
|
}
|
|
var isClosing = false;
|
/**
|
* 收到 WebSocket 断开的消息,处理断开逻辑
|
*/
|
function handleSocketClose(res) {
|
dispatchEvent('close', res);
|
|
/* istanbul ignore if */
|
if (isClosing) return;
|
|
/* istanbul ignore else */
|
if (isActive()) {
|
close()
|
}
|
}
|
|
function close(emitClose) {
|
isClosing = true;
|
closeSocket(emitClose);
|
setStatus(STATUS_CLOSED);
|
dispatchEvent('close');
|
isClosing = false;
|
}
|
|
function closeSocket(emitClose) {
|
if (isActive() && emitClose !== false) {
|
wx.sendSocketMessage({
|
data: JSON.stringify({
|
"type": "Close", "data": "", "extra": ""
|
}),complete:function(res){
|
console.log(res)
|
},
|
})
|
}
|
|
wx.closeSocket({
|
complete: function (res) {
|
console.log('WebSocket连接关闭!' + res.errMsg)
|
}
|
})
|
}
|
|
//=========================================================================
|
// 错误处理
|
//=========================================================================
|
|
/**
|
* 错误处理
|
*/
|
function handleSocketError(detail) {
|
dispatchEvent('error', detail)
|
}
|
|
}
|
|
module.exports = SocketTunnel;
|