140 lines
3.5 KiB
JavaScript
Raw Normal View History

const _utils = require('../../../../common/utils');
const MAX_AMOUNT_WEBSOCKET = 1 // The maximum number of WEBSOCKET
let CURR_AMOUNT_WEBSOCKET = 0 // The current number of WEBSOCKET
export default class WebSocket {
static CONNECTING = 0 // The connection is not yet open.
static OPEN = 1 // The connection is open and ready to communicate.
static CLOSING = 2 // The connection is in the process of closing.
static CLOSED = 3 // The connection is closed or couldn't be opened.
binaryType = '' // TODO 更新 binaryType
bufferedAmount = 0 // TODO 更新 bufferedAmount
extensions = ''
onopen = null
onmessage = null
onerror = null
onclose = null
_onMessage = null
_onOpen = null
_onError = null
_onClose = null
_isReduced = false
protocol = '' // TODO 小程序内目前获取不到,实际上需要根据服务器选择的 sub-protocol 返回
readyState = 3
constructor(url, protocols = []) {
if(this._isMaxCount()){
console.warn(`Failed to construct 'WebSocket': Only ${CURR_AMOUNT_WEBSOCKET} WebSocket can be created at the same time on TaoBao.`);
return this;
}
if (typeof url !== 'string' || !(/(^ws:\/\/)|(^wss:\/\/)/).test(url)) {
throw new TypeError(`Failed to construct 'WebSocket': The URL '${url}' is invalid`)
}
this.url = url
this.readyState = WebSocket.CONNECTING
this._increaseCount();
my.connectSocket({
url,
fail: function fail(res) {
this._triggerEvent('error', res)
}
})
this._onOpen = (res) => {
this.readyState = WebSocket.OPEN
this._triggerEvent('open')
}
my.onSocketOpen(this._onOpen)
this._onMessage = (res) => {
if (res && res.data && res.isBuffer) {
res.data = _utils.base64ToArrayBuffer(res.data)
}
this._triggerEvent('message', res)
}
my.onSocketMessage(this._onMessage)
this._onError = (res) => {
this._triggerEvent('error', res)
this._decreaseCount();
}
my.onSocketError(this._onError)
this._onClose = (res) => {
this.readyState = WebSocket.CLOSED
this._triggerEvent('close')
this._removeAllSocketListenr()
this._decreaseCount();
}
my.onSocketClose(this._onClose)
return this
}
close() {
this.readyState = WebSocket.CLOSING
my.closeSocket()
}
send(data) {
if (typeof data !== 'string' && !(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)) {
throw new TypeError(`Failed to send message: The data ${data} is invalid`)
}else{
var isBuffer = false;
if (data instanceof ArrayBuffer) {
data = _utils.arrayBufferToBase64(data)
isBuffer = true
}
my.sendSocketMessage({
data,
isBuffer,
fail: function (res) {
this._triggerEvent('error', res)
}
});
}
}
_triggerEvent(type, ...args) {
if (typeof this[`on${type}`] === 'function') {
this[`on${type}`].apply(this, args)
}
}
_removeAllSocketListenr(){
my.offSocketOpen(this._onOpen)
my.offSocketMessage(this._onMessage)
my.offSocketError(this._onError)
my.offSocketClose(this._onClose)
this._onOpen = null
this._onMessage = null
this._onError = null
this._onClose = null
}
_increaseCount(){
CURR_AMOUNT_WEBSOCKET += 1
}
_decreaseCount(){
if(!this._isReduced){
CURR_AMOUNT_WEBSOCKET -= 1
this._isReduced = true
}
}
_isMaxCount(){
return CURR_AMOUNT_WEBSOCKET >= MAX_AMOUNT_WEBSOCKET
}
}