mirror of
https://github.com/Gongxh0901/kunpolibrary
synced 2025-04-10 21:51:04 +00:00
websocket
This commit is contained in:
parent
7294959799
commit
7df6c99b0d
3612
libs/lib.ali.api.d.ts
vendored
Normal file
3612
libs/lib.ali.api.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
153
libs/lib.wx.api.d.ts
vendored
Normal file
153
libs/lib.wx.api.d.ts
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
/**
|
||||
* @Author: Gongxh
|
||||
* @Date: 2025-03-28
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
declare namespace WechatMiniprogram {
|
||||
type IAnyObject = Record<string, any>
|
||||
|
||||
interface ICommonCallBack {
|
||||
/**
|
||||
* 接口调用成功的回调函数
|
||||
*/
|
||||
success?: () => void;
|
||||
|
||||
/**
|
||||
* 接口调用失败的回调函数
|
||||
*/
|
||||
fail?: () => void;
|
||||
|
||||
/**
|
||||
* 接口调用结束的回调函数(调用成功、失败都会执行)
|
||||
*/
|
||||
complete?: () => void;
|
||||
}
|
||||
|
||||
interface ConnectSocketOption extends ICommonCallBack {
|
||||
/** 开发者服务器 wss 接口地址 */
|
||||
url: string
|
||||
|
||||
/** HTTP Header,Header 中不能设置 Referer */
|
||||
header?: IAnyObject
|
||||
|
||||
/**
|
||||
* 需要基础库: '1.4.0'
|
||||
* 子协议数组
|
||||
*/
|
||||
protocols?: string[]
|
||||
|
||||
/**
|
||||
* 需要基础库: '2.4.0'
|
||||
* 建立 TCP 连接的时候的 TCP_NODELAY 设置
|
||||
*/
|
||||
tcpNoDelay?: boolean
|
||||
|
||||
/**
|
||||
* 需要基础库: '2.8.0'
|
||||
* 是否开启压缩扩展
|
||||
*/
|
||||
perMessageDeflate?: boolean
|
||||
|
||||
/**
|
||||
* 需要基础库: '2.10.0'
|
||||
* 超时时间,单位为毫秒
|
||||
*/
|
||||
timeout?: number
|
||||
|
||||
/**
|
||||
* 需要基础库: '2.29.0'
|
||||
* 强制使用蜂窝网络发送请求
|
||||
*/
|
||||
forceCellularNetwork?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要基础库: `2.10.4`
|
||||
* 网络请求过程中一些调试信息
|
||||
*/
|
||||
interface SocketProfile {
|
||||
/** 组件准备好使用 SOCKET 建立请求的时间,这发生在检查本地缓存之前 */
|
||||
fetchStart: number;
|
||||
/** DNS 域名查询开始的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等 */
|
||||
domainLookupStart: number;
|
||||
/** DNS 域名查询完成的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等 */
|
||||
domainLookupEnd: number;
|
||||
/** 开始建立连接的时间,如果是持久连接,则与 fetchStart 值相等。注意如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接开始的时间 */
|
||||
connectStart: number;
|
||||
/** 完成建立连接的时间(完成握手),如果是持久连接,则与 fetchStart 值相等。注意如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接完成的时间。注意这里握手结束,包括安全连接建立完成、SOCKS 授权通过 */
|
||||
connectEnd: number;
|
||||
/** 单次连接的耗时,包括 connect ,tls */
|
||||
rtt: number;
|
||||
/** 握手耗时 */
|
||||
handshakeCost: number;
|
||||
/** 上层请求到返回的耗时 */
|
||||
cost: number;
|
||||
}
|
||||
|
||||
interface SocketSendOption extends ICommonCallBack {
|
||||
/** 需要发送的消息 */
|
||||
data: string | ArrayBuffer;
|
||||
}
|
||||
interface SocketCloseOption extends ICommonCallBack {
|
||||
/**
|
||||
* 1000(表示正常关闭连接)
|
||||
* 关闭代码
|
||||
*/
|
||||
code?: number;
|
||||
/**
|
||||
* 关闭原因
|
||||
* 这个字符串必须是不长于 123 字节的 UTF-8 文本
|
||||
*/
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
interface SocketTask {
|
||||
/**
|
||||
* 发送消息
|
||||
* @param data 需要发送的消息
|
||||
*/
|
||||
send(res: SocketSendOption): void
|
||||
|
||||
/**
|
||||
* 关闭 WebSocket 连接
|
||||
* @param code 关闭代码
|
||||
* @param reason 关闭原因
|
||||
*/
|
||||
close(res: SocketCloseOption): void
|
||||
|
||||
/**
|
||||
* 监听 WebSocket 连接打开事件
|
||||
* @param listener
|
||||
*/
|
||||
onOpen(listener: (res: { header: IAnyObject, profile: SocketProfile }) => void): void
|
||||
|
||||
/**
|
||||
* 监听 WebSocket 接收到消息事件
|
||||
* @param listener
|
||||
* @param res.data 服务器返回的消息
|
||||
*/
|
||||
onMessage(listener: (res: { data: string | ArrayBuffer }) => void): void
|
||||
|
||||
/**
|
||||
* 监听 WebSocket 错误事件
|
||||
* @param listener
|
||||
* @param res.errMsg 错误信息
|
||||
*/
|
||||
onError(listener: (res: { errMsg: string }) => void): void
|
||||
|
||||
/**
|
||||
* 监听 WebSocket 关闭事件
|
||||
* @param listener
|
||||
* @param res.code 关闭代码
|
||||
* @param res.reason 关闭原因
|
||||
*/
|
||||
onClose(listener: (res: { code: number, reason: string }) => void): void
|
||||
}
|
||||
|
||||
interface Wx {
|
||||
connectSocket(option: ConnectSocketOption): SocketTask
|
||||
}
|
||||
}
|
||||
|
||||
declare const wx: WechatMiniprogram.Wx
|
@ -44,6 +44,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cocos/creator-types": "^3.8.0",
|
||||
"@douyin-microapp/typings": "^1.3.1",
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@rollup/plugin-typescript": "^12.1.2",
|
||||
"@types/lodash": "^4.17.13",
|
||||
|
@ -7,7 +7,7 @@
|
||||
import { screen as ccScreen, view } from "cc";
|
||||
import { Adapter } from "../global/Adapter";
|
||||
import { size } from "../global/header";
|
||||
import { info } from "../tool/log";
|
||||
import { debug } from "../tool/log";
|
||||
|
||||
export class CocosAdapter extends Adapter {
|
||||
/**
|
||||
@ -39,15 +39,15 @@ export class CocosAdapter extends Adapter {
|
||||
*/
|
||||
protected registerResizeCallback(callback: (...args: any) => void): void {
|
||||
ccScreen.on("window-resize", (...args: any) => {
|
||||
info("window-resize");
|
||||
debug("window-resize");
|
||||
callback(...args);
|
||||
}, this);
|
||||
ccScreen.on("orientation-change", (...args: any) => {
|
||||
info("orientation-change");
|
||||
debug("orientation-change");
|
||||
callback(...args);
|
||||
}, this);
|
||||
ccScreen.on("fullscreen-change", (...args: any) => {
|
||||
info("fullscreen-change");
|
||||
debug("fullscreen-change");
|
||||
callback(...args);
|
||||
}, this);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import { InnerTimer } from "../global/InnerTimer";
|
||||
import { Platform, PlatformType } from "../global/Platform";
|
||||
import { ECManager } from "../kunpocc";
|
||||
import { ModuleBase } from "../module/ModuleBase";
|
||||
import { info } from "../tool/log";
|
||||
import { debug, log } from "../tool/log";
|
||||
import { Time } from "../tool/Time";
|
||||
import { PropsHelper } from "../ui/PropsHelper";
|
||||
import { CocosAdapter } from "./CocosAdapter";
|
||||
@ -38,7 +38,7 @@ export abstract class CocosEntry extends Component {
|
||||
* @internal
|
||||
*/
|
||||
protected start(): void {
|
||||
info("开始初始化kunpo框架");
|
||||
log("开始初始化kunpo框架");
|
||||
|
||||
const config = this.getConfig();
|
||||
enableDebugMode(config.debug);
|
||||
@ -56,7 +56,7 @@ export abstract class CocosEntry extends Component {
|
||||
this.initModule();
|
||||
// 注册所有组件
|
||||
ECDataHelper.registerComponents();
|
||||
info("kunpo框架初始化完成");
|
||||
log("kunpo框架初始化完成");
|
||||
this.onInit();
|
||||
}
|
||||
|
||||
@ -73,15 +73,15 @@ export abstract class CocosEntry extends Component {
|
||||
switch (sys.os) {
|
||||
case sys.OS.ANDROID:
|
||||
Platform.isAndroid = true;
|
||||
info("系统类型 Android");
|
||||
debug("系统类型 Android");
|
||||
break;
|
||||
case sys.OS.IOS:
|
||||
Platform.isIOS = true;
|
||||
info("系统类型 IOS");
|
||||
debug("系统类型 IOS");
|
||||
break;
|
||||
case sys.OS.OPENHARMONY:
|
||||
Platform.isHarmonyOS = true;
|
||||
info("系统类型 HarmonyOS");
|
||||
debug("系统类型 HarmonyOS");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -110,7 +110,7 @@ export abstract class CocosEntry extends Component {
|
||||
Platform.platform = PlatformType.Browser;
|
||||
break;
|
||||
}
|
||||
info(`platform: ${PlatformType[Platform.platform]}`);
|
||||
debug(`platform: ${PlatformType[Platform.platform]}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,10 +145,10 @@ export abstract class CocosEntry extends Component {
|
||||
* @internal
|
||||
*/
|
||||
private initModule(): void {
|
||||
info(`初始化模块`);
|
||||
debug(`初始化模块`);
|
||||
// 递归查找自身或所有子节点中指定类型的组件。
|
||||
for (const module of this.getComponentsInChildren(ModuleBase)) {
|
||||
info(`module:${module.moduleName}`);
|
||||
debug(`module:${module.moduleName}`);
|
||||
module.init();
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,10 @@
|
||||
* @Date: 2024-12-07
|
||||
* @Description: cocos UI模块
|
||||
*/
|
||||
import { _decorator } from "cc";
|
||||
import { _decorator, debug } from "cc";
|
||||
|
||||
import { GRoot } from "fairygui-cc";
|
||||
import { ModuleBase } from "../module/ModuleBase";
|
||||
import { info } from "../tool/log";
|
||||
import { WindowManager } from "../ui/WindowManager";
|
||||
import { WindowResPool } from "../ui/WindowResPool";
|
||||
import { CocosWindowContainer } from "./CocosWindowContainer";
|
||||
@ -24,7 +23,7 @@ export class CocosUIModule extends ModuleBase {
|
||||
/** 初始化窗口管理系统 */
|
||||
WindowManager._init(new WindowResPool());
|
||||
GRoot.create();
|
||||
info("初始化 WindowContainers");
|
||||
debug("初始化 WindowContainers");
|
||||
for (const child of this.node.children) {
|
||||
const containerComponent = child.getComponent(CocosWindowContainer);
|
||||
containerComponent?.init();
|
||||
@ -40,6 +39,6 @@ export class CocosUIModule extends ModuleBase {
|
||||
|
||||
/** 模块初始化完成后调用的函数 */
|
||||
protected onInit(): void {
|
||||
info("UIModule init complete");
|
||||
debug("UIModule init complete");
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
import { Component, _decorator } from "cc";
|
||||
import { GComponent, GRoot } from "fairygui-cc";
|
||||
import { Screen } from "../global/Screen";
|
||||
import { info } from "../tool/log";
|
||||
import { debug } from "../tool/log";
|
||||
import { WindowGroup } from "../ui/WindowGroup";
|
||||
import { WindowManager } from "../ui/WindowManager";
|
||||
const { ccclass, property, menu } = _decorator;
|
||||
@ -23,7 +23,7 @@ export class CocosWindowContainer extends Component {
|
||||
*/
|
||||
public init(): void {
|
||||
let name = this.node.name;
|
||||
info(`\tUIContainer name:${name} 忽略顶部窗口查询:${this.ignoreQuery} 吞噬触摸事件:${this.swallowTouch}`);
|
||||
debug(`\tUIContainer name:${name} 忽略顶部窗口查询:${this.ignoreQuery} 吞噬触摸事件:${this.swallowTouch}`);
|
||||
const root = new GComponent();
|
||||
root.name = name;
|
||||
root.node.name = name;
|
||||
|
@ -6,7 +6,7 @@
|
||||
import { _decorator } from "cc";
|
||||
import { InnerTimer } from "../global/InnerTimer";
|
||||
import { ModuleBase } from "../module/ModuleBase";
|
||||
import { info } from "../tool/log";
|
||||
import { debug } from "../tool/log";
|
||||
import { ConditionManager } from "./ConditionManager";
|
||||
|
||||
const { ccclass, menu, property } = _decorator;
|
||||
@ -36,7 +36,7 @@ export class ConditionModule extends ModuleBase {
|
||||
|
||||
/** 模块初始化完成后调用的函数 */
|
||||
protected onInit(): void {
|
||||
info("ConditionModule init complete");
|
||||
debug("ConditionModule init complete");
|
||||
}
|
||||
|
||||
public onDestroy(): void {
|
||||
|
@ -4,8 +4,7 @@
|
||||
* @Description: 适配用的类
|
||||
*/
|
||||
|
||||
import { ResolutionPolicy, view } from "cc";
|
||||
import { info } from "../tool/log";
|
||||
import { debug, ResolutionPolicy, view } from "cc";
|
||||
import { WindowManager } from "../ui/WindowManager";
|
||||
import { Screen } from "./Screen";
|
||||
import { size } from "./header";
|
||||
@ -21,7 +20,7 @@ export abstract class Adapter {
|
||||
|
||||
this.resize();
|
||||
this.registerResizeCallback((...args: any) => {
|
||||
info("屏幕发生变化", ...args);
|
||||
debug("屏幕发生变化", ...args);
|
||||
this.resize();
|
||||
});
|
||||
}
|
||||
@ -59,10 +58,10 @@ export abstract class Adapter {
|
||||
|
||||
/** @internal */
|
||||
private printScreen() {
|
||||
info(`设计分辨率: ${Screen.DesignWidth}x${Screen.DesignHeight}`);
|
||||
info(`屏幕分辨率: ${Screen.ScreenWidth}x${Screen.ScreenHeight}`);
|
||||
info(`安全区域高度: ${Screen.SafeAreaHeight}`);
|
||||
info(`安全区宽高: ${Screen.SafeWidth}x${Screen.SafeHeight}`);
|
||||
debug(`设计分辨率: ${Screen.DesignWidth}x${Screen.DesignHeight}`);
|
||||
debug(`屏幕分辨率: ${Screen.ScreenWidth}x${Screen.ScreenHeight}`);
|
||||
debug(`安全区域高度: ${Screen.SafeAreaHeight}`);
|
||||
debug(`安全区宽高: ${Screen.SafeWidth}x${Screen.SafeHeight}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,13 +14,16 @@ export { Time } from "./tool/Time";
|
||||
/** 消息监听 */
|
||||
export { EventManager } from "./event/EventManager";
|
||||
|
||||
/** 网络 */
|
||||
/** Http */
|
||||
export * from "./net/http/HttpManager";
|
||||
export { HttpTask } from "./net/http/HttpTask";
|
||||
export { IHttpEvent } from "./net/http/IHttpEvent";
|
||||
export { IHttpRequest } from "./net/http/IHttpRequest";
|
||||
export { IHttpResponse } from "./net/http/IHttpResponse";
|
||||
|
||||
/** Socket */
|
||||
export { Socket } from "./net/socket/Socket";
|
||||
|
||||
/** 四叉树 */
|
||||
export { Box } from "./quadtree/Box";
|
||||
export { Circle } from "./quadtree/Circle";
|
||||
|
297
src/net/socket/Socket.ts
Normal file
297
src/net/socket/Socket.ts
Normal file
@ -0,0 +1,297 @@
|
||||
/**
|
||||
* @Author: Gongxh
|
||||
* @Date: 2025-03-28
|
||||
* @Description: 网络socket
|
||||
*/
|
||||
|
||||
import { SocketTask } from "@douyin-microapp/typings/types/api";
|
||||
import { Platform } from "../../global/Platform";
|
||||
import { debug, warn } from "../../tool/log";
|
||||
|
||||
type BinaryType = "blob" | "arraybuffer";
|
||||
|
||||
interface SocketOptions {
|
||||
/**
|
||||
* 给原生平台 和 web 用
|
||||
* 一个协议字符串或者一个包含协议字符串的数组。
|
||||
* 这些字符串用于指定子协议,这样单个服务器可以实现多个 WebSocket 子协议(
|
||||
* 例如,你可能希望一台服务器能够根据指定的协议(protocol)处理不同类型的交互。
|
||||
* 如果不指定协议字符串,则假定为空字符串。
|
||||
*/
|
||||
protocols?: string[];
|
||||
|
||||
/**
|
||||
* 使用 Blob 对象处理二进制数据。这是默认值
|
||||
* 使用 ArrayBuffer 对象处理二进制数据
|
||||
* @url https://developer.mozilla.org/docs/Web/API/WebSocket/binaryType
|
||||
*/
|
||||
binaryType?: BinaryType;
|
||||
|
||||
/** 超时时间 默认3000毫秒 */
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
export class Socket {
|
||||
/**
|
||||
* socket对象
|
||||
* @internal
|
||||
*/
|
||||
private _socket: WebSocket | WechatMiniprogram.SocketTask | AliyMiniprogram.SocketTask | SocketTask;
|
||||
|
||||
/**
|
||||
* @param {string} url 要连接的 URL;这应该是 WebSocket 服务器将响应的 URL
|
||||
* @param {SocketOptions} options 可选参数 针对不同平台的一些特殊参数 详细信息见定义
|
||||
*/
|
||||
constructor(url: string, options?: SocketOptions) {
|
||||
if (Platform.isWX) {
|
||||
this._socket = this.createWechatSocket(url, options?.timeout || 3000, options?.protocols);
|
||||
} else if (Platform.isAlipay) {
|
||||
this._socket = this.createAliSocket(url, options?.timeout || 3000, options?.protocols);
|
||||
} else if (Platform.isBytedance) {
|
||||
this._socket = this.createBytedanceSocket(url, options?.timeout || 3000, options?.protocols);
|
||||
} else {
|
||||
this._socket = this.createOtherSocket(url, options?.binaryType, options?.timeout || 3000, options?.protocols);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信小游戏创建socket
|
||||
* @internal
|
||||
*/
|
||||
private createWechatSocket(url: string, timeout?: number, protocols?: string[]): WechatMiniprogram.SocketTask {
|
||||
let socket = wx.connectSocket({
|
||||
url,
|
||||
protocols: protocols,
|
||||
timeout: timeout,
|
||||
success: () => { debug("socket success") },
|
||||
fail: () => { warn("socket fail") }
|
||||
});
|
||||
socket.onOpen(() => {
|
||||
this.onopen && this.onopen();
|
||||
});
|
||||
socket.onMessage((res: { data: string | ArrayBuffer }) => {
|
||||
this.onmessage && this.onmessage(res.data);
|
||||
});
|
||||
socket.onError((res: { errMsg: string }) => {
|
||||
// 微信上socket和原生平台以及浏览器不一致 所以这里特殊处理 给他一个默认的错误码
|
||||
this.onclose?.(1000, res?.errMsg);
|
||||
});
|
||||
socket.onClose((res: { code: number, reason: string }) => {
|
||||
this.onclose?.(res.code, res.reason);
|
||||
});
|
||||
return socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝小游戏创建socket
|
||||
* @internal
|
||||
*/
|
||||
private createAliSocket(url: string, timeout?: number, protocols?: string[]): AliyMiniprogram.SocketTask {
|
||||
let socket = my.connectSocket({
|
||||
url,
|
||||
protocols: protocols,
|
||||
multiple: true,
|
||||
timeout: timeout,
|
||||
success: () => { debug("socket success") },
|
||||
fail: () => { warn("socket fail") }
|
||||
});
|
||||
|
||||
socket.onOpen((info: AliyMiniprogram.OnOpenData) => {
|
||||
this.onopen && this.onopen();
|
||||
});
|
||||
socket.onMessage((info: AliyMiniprogram.OnMessageData) => {
|
||||
if (!this.onmessage) {
|
||||
return;
|
||||
}
|
||||
if (info.isBuffer) {
|
||||
if (my.base64ToArrayBuffer) {
|
||||
this.onmessage(my.base64ToArrayBuffer(info.data.data));
|
||||
} else if (atob) {
|
||||
this.onmessage(this.base64ToArrayBuffer(info.data.data));
|
||||
} else {
|
||||
this.onmessage(info.data.data);
|
||||
}
|
||||
this.onmessage(info.data.data);
|
||||
} else {
|
||||
this.onmessage(info.data.data);
|
||||
}
|
||||
});
|
||||
socket.onError((info: { data: AliyMiniprogram.CallBack.Fail }) => {
|
||||
this.onclose && this.onclose(info.data.error, info.data.errorMessage);
|
||||
});
|
||||
socket.onClose((info: { code: number, reason: string, data: { code: number, reason: string } }) => {
|
||||
this.onclose && this.onclose(info.code, info.reason);
|
||||
});
|
||||
return socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* 抖音小游戏创建socket
|
||||
* @internal
|
||||
*/
|
||||
private createBytedanceSocket(url: string, timeout?: number, protocols?: string[]): SocketTask {
|
||||
let socket: SocketTask = tt.connectSocket({
|
||||
url,
|
||||
protocols: protocols,
|
||||
success: () => { debug("socket success") },
|
||||
fail: () => { warn("socket fail") }
|
||||
});
|
||||
|
||||
let timer = setTimeout(() => {
|
||||
socket.close({});
|
||||
}, timeout);
|
||||
|
||||
socket.onOpen(() => {
|
||||
timer && clearTimeout(timer);
|
||||
timer = null;
|
||||
this.onopen && this.onopen();
|
||||
});
|
||||
socket.onMessage((info: { data: string | ArrayBuffer }) => {
|
||||
this.onmessage && this.onmessage(info.data);
|
||||
});
|
||||
socket.onError((res: { errMsg: string }) => {
|
||||
timer && clearTimeout(timer);
|
||||
timer = null;
|
||||
// 微信上socket和原生平台以及浏览器不一致 所以这里特殊处理 给他一个默认的错误码
|
||||
this.onclose?.(1000, res.errMsg);
|
||||
});
|
||||
socket.onClose((res: { code: string, reason: string }) => {
|
||||
timer && clearTimeout(timer);
|
||||
timer = null;
|
||||
this.onclose?.(Number(res.code), res.reason);
|
||||
});
|
||||
return socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* 除微信小游戏、支付宝小游戏、抖音小游戏之外的平台创建socket
|
||||
* @internal
|
||||
*/
|
||||
private createOtherSocket(url: string, binaryType: BinaryType, timeout?: number, protocols?: string[]): WebSocket {
|
||||
let socket = new WebSocket(url, protocols);
|
||||
if (binaryType) {
|
||||
socket.binaryType = binaryType;
|
||||
}
|
||||
|
||||
let timer = setTimeout(() => {
|
||||
socket.close();
|
||||
}, timeout);
|
||||
|
||||
socket.onopen = () => {
|
||||
timer && clearTimeout(timer);
|
||||
timer = null;
|
||||
this.onopen?.();
|
||||
}
|
||||
socket.onmessage = (event: MessageEvent) => {
|
||||
this.onmessage?.(event.data);
|
||||
}
|
||||
socket.onerror = () => {
|
||||
timer && clearTimeout(timer);
|
||||
timer = null;
|
||||
this.onerror?.();
|
||||
}
|
||||
socket.onclose = (event: CloseEvent) => {
|
||||
timer && clearTimeout(timer);
|
||||
timer = null;
|
||||
this.onclose?.(event?.code, event?.reason);
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
* @param data - 消息数据
|
||||
*/
|
||||
public send(data: string | ArrayBuffer): void {
|
||||
if (Platform.isWX) {
|
||||
(this._socket as WechatMiniprogram.SocketTask).send({ data: data });
|
||||
} else if (Platform.isAlipay) {
|
||||
(this._socket as AliyMiniprogram.SocketTask).send({ data: data });
|
||||
} else if (Platform.isBytedance) {
|
||||
(this._socket as SocketTask).send({ data: data });
|
||||
} else {
|
||||
(this._socket as WebSocket).send(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户端主动断开
|
||||
* @param code - 关闭代码: 如果没有传这个参数,默认使用1000, 客户端可使用的数字范围: [3001-3999]
|
||||
* @param reason - 关闭原因: 一个人类可读的字符串,它解释了连接关闭的原因。这个 UTF-8 编码的字符串不能超过 123 个字节
|
||||
*/
|
||||
public close(code?: number, reason?: string): void {
|
||||
if (Platform.isWX) {
|
||||
(this._socket as WechatMiniprogram.SocketTask).close({ code: code, reason: reason });
|
||||
} else if (Platform.isAlipay) {
|
||||
(this._socket as AliyMiniprogram.SocketTask).closeSocket({ code: code, reason: reason });
|
||||
} else {
|
||||
(this._socket as WebSocket).close(code, reason);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取socket示例
|
||||
* 在微信小游戏、支付宝小游戏、抖音小游戏 返回的是他们平台的socket实例类型
|
||||
*/
|
||||
public socket(): WebSocket | any {
|
||||
return this._socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* socket已准备好 open成功
|
||||
* 当前连接已经准备好发送和接受数据
|
||||
*/
|
||||
public onopen: () => void;
|
||||
|
||||
/**
|
||||
* 接收到服务端发送的消息
|
||||
* @param data - 消息数据
|
||||
*/
|
||||
public onmessage: (data: any) => void;
|
||||
|
||||
/**
|
||||
* 监听可能发生的错误,一般用不到
|
||||
*/
|
||||
public onerror: () => void;
|
||||
|
||||
/**
|
||||
* 关闭连接
|
||||
* @param code - 关闭代码
|
||||
* @param reason - 关闭原因
|
||||
*/
|
||||
public onclose: (code: number, reason: string) => void;
|
||||
|
||||
/**
|
||||
* 二进制数据转成Base64 (支付宝用)
|
||||
* @internal
|
||||
*/
|
||||
private uint8ArrayToBase64(u8Array: Uint8Array): string {
|
||||
let CHUNK_SIZE = 0x8000; // 32768
|
||||
let index = 0;
|
||||
let length = u8Array.length;
|
||||
let result = '';
|
||||
let slice: Uint8Array<ArrayBufferLike>;;
|
||||
|
||||
// 分段处理,避免`btoa`输入字符串过长
|
||||
for (; index < length; index += CHUNK_SIZE) {
|
||||
slice = u8Array.subarray(index, Math.min(index + CHUNK_SIZE, length));
|
||||
// 将Uint8Array转换为字符串并使用btoa进行Base64编码
|
||||
result += btoa(String.fromCharCode(...slice));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* base64转成ArrayBuffer (支付宝用)
|
||||
* @internal
|
||||
*/
|
||||
private base64ToArrayBuffer(base64: string): ArrayBuffer {
|
||||
let binary_string = atob(base64);
|
||||
let len = binary_string.length;
|
||||
let bytes = new Uint8Array(len);
|
||||
for (var i = 0; i < len; i++) {
|
||||
bytes[i] = binary_string.charCodeAt(i);
|
||||
}
|
||||
return bytes.buffer;
|
||||
}
|
||||
}
|
@ -12,6 +12,9 @@
|
||||
"types": [
|
||||
"@cocos/creator-types/engine",
|
||||
"@cocos/creator-types/editor",
|
||||
"./libs/lib.wx.api.d.ts",
|
||||
"./libs/lib.ali.api.d.ts",
|
||||
"@douyin-microapp/typings"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
|
Loading…
x
Reference in New Issue
Block a user