抽象worker接口,避免污染项目

This commit is contained in:
YHH
2025-09-29 18:15:47 +08:00
parent 62bc6b547e
commit 90ad4b3ec4
14 changed files with 2027 additions and 931 deletions

View File

@@ -58,7 +58,7 @@
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-terser": "^0.4.4",
"@types/jest": "^29.5.14",
"@types/node": "^20.19.0",
"@types/node": "^20.19.17",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"rimraf": "^5.0.0",

View File

@@ -1,278 +0,0 @@
import type {
IPlatformAdapter,
PlatformWorker,
WorkerCreationOptions,
PlatformConfig,
BrowserDeviceInfo
} from './IPlatformAdapter';
import { createLogger, type ILogger } from '../Utils/Logger';
/**
* 浏览器平台适配器
* 支持标准Web API的浏览器环境
*/
export class BrowserAdapter implements IPlatformAdapter {
public readonly name = 'browser';
public readonly version = this.getBrowserVersion();
private readonly logger: ILogger;
constructor() {
this.logger = createLogger('BrowserAdapter');
}
/**
* 检查是否支持Worker
*/
public isWorkerSupported(): boolean {
return typeof Worker !== 'undefined' && typeof Blob !== 'undefined' && typeof URL !== 'undefined';
}
/**
* 检查是否支持SharedArrayBuffer
*/
public isSharedArrayBufferSupported(): boolean {
return typeof SharedArrayBuffer !== 'undefined' &&
typeof self !== 'undefined' &&
self.crossOriginIsolated === true;
}
/**
* 获取硬件并发数
*/
public getHardwareConcurrency(): number {
if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) {
return navigator.hardwareConcurrency;
}
return 4; // 默认值
}
/**
* 创建Worker
*/
public createWorker(script: string, options: WorkerCreationOptions = {}): PlatformWorker {
const blob = new Blob([script], { type: 'application/javascript' });
const scriptURL = URL.createObjectURL(blob);
const worker = new Worker(scriptURL, {
type: options.type || 'classic',
credentials: options.credentials || 'same-origin',
name: options.name
});
return new BrowserWorker(worker, scriptURL);
}
/**
* 创建SharedArrayBuffer
*/
public createSharedArrayBuffer(length: number): SharedArrayBuffer | null {
if (!this.isSharedArrayBufferSupported()) {
return null;
}
try {
return new SharedArrayBuffer(length);
} catch (error) {
this.logger.warn('Failed to create SharedArrayBuffer:', error);
return null;
}
}
/**
* 获取高精度时间戳
*/
public getHighResTimestamp(): number {
if (typeof performance !== 'undefined' && performance.now) {
return performance.now();
}
return Date.now();
}
/**
* 获取平台配置
*/
public getPlatformConfig(): PlatformConfig {
return {
maxWorkerCount: this.getHardwareConcurrency(),
supportsModuleWorker: this.supportsModuleWorker(),
supportsTransferableObjects: this.supportsTransferableObjects(),
maxSharedArrayBufferSize: this.getMaxSharedArrayBufferSize(),
workerScriptPrefix: '',
limitations: {
noEval: false,
requiresWorkerInit: false
},
extensions: {
supportsServiceWorker: typeof navigator !== 'undefined' && 'serviceWorker' in navigator,
supportsWebAssembly: typeof WebAssembly !== 'undefined'
}
};
}
/**
* 获取浏览器设备信息
*/
public getDeviceInfo(): BrowserDeviceInfo {
try {
const deviceInfo: BrowserDeviceInfo = {};
// 浏览器基础信息
if (typeof navigator !== 'undefined') {
deviceInfo.userAgent = navigator.userAgent;
deviceInfo.vendor = navigator.vendor;
deviceInfo.language = navigator.language;
deviceInfo.languages = navigator.languages as string[];
deviceInfo.cookieEnabled = navigator.cookieEnabled;
deviceInfo.onLine = navigator.onLine;
deviceInfo.doNotTrack = navigator.doNotTrack;
deviceInfo.platform = navigator.platform;
deviceInfo.appVersion = navigator.appVersion;
deviceInfo.appName = navigator.appName;
// 硬件信息
deviceInfo.hardwareConcurrency = navigator.hardwareConcurrency;
deviceInfo.maxTouchPoints = navigator.maxTouchPoints;
// 设备内存实验性API
if ('deviceMemory' in navigator) {
deviceInfo.deviceMemory = (navigator as any).deviceMemory;
}
// 网络连接信息实验性API
if ('connection' in navigator) {
const connection = (navigator as any).connection;
deviceInfo.connection = {
effectiveType: connection.effectiveType,
downlink: connection.downlink,
rtt: connection.rtt,
saveData: connection.saveData
};
}
}
// 屏幕信息
if (typeof screen !== 'undefined') {
deviceInfo.screenWidth = screen.width;
deviceInfo.screenHeight = screen.height;
deviceInfo.availWidth = screen.availWidth;
deviceInfo.availHeight = screen.availHeight;
deviceInfo.colorDepth = screen.colorDepth;
deviceInfo.pixelDepth = screen.pixelDepth;
}
// 窗口信息
if (typeof window !== 'undefined') {
deviceInfo.innerWidth = window.innerWidth;
deviceInfo.innerHeight = window.innerHeight;
deviceInfo.outerWidth = window.outerWidth;
deviceInfo.outerHeight = window.outerHeight;
deviceInfo.devicePixelRatio = window.devicePixelRatio;
}
return deviceInfo;
} catch (error) {
this.logger.warn('获取浏览器设备信息失败', error);
return {} as BrowserDeviceInfo;
}
}
/**
* 获取浏览器版本信息
*/
private getBrowserVersion(): string {
if (typeof navigator !== 'undefined') {
return navigator.userAgent;
}
return 'unknown';
}
/**
* 检查是否支持模块Worker
*/
private supportsModuleWorker(): boolean {
try {
// 尝试创建一个简单的模块Worker来测试支持
const blob = new Blob(['export {};'], { type: 'application/javascript' });
const url = URL.createObjectURL(blob);
const worker = new Worker(url, { type: 'module' });
worker.terminate();
URL.revokeObjectURL(url);
return true;
} catch {
return false;
}
}
/**
* 检查是否支持Transferable Objects
*/
private supportsTransferableObjects(): boolean {
try {
const buffer = new ArrayBuffer(8);
const blob = new Blob(['self.postMessage(null);'], { type: 'application/javascript' });
const url = URL.createObjectURL(blob);
const worker = new Worker(url);
worker.postMessage(buffer, [buffer]);
worker.terminate();
URL.revokeObjectURL(url);
return buffer.byteLength === 0; // Buffer应该被transfer走
} catch {
return false;
}
}
/**
* 获取SharedArrayBuffer最大大小限制
*/
private getMaxSharedArrayBufferSize(): number {
// 浏览器环境返回保守的默认值
// 大多数现代浏览器都支持较大的SharedArrayBuffer
return 256 * 1024 * 1024; // 256MB适合大多数ECS应用场景
}
}
/**
* 浏览器Worker封装
*/
class BrowserWorker implements PlatformWorker {
private _state: 'running' | 'terminated' = 'running';
constructor(
private worker: Worker,
private scriptURL: string
) {}
public get state(): 'running' | 'terminated' {
return this._state;
}
public postMessage(message: any, transfer?: Transferable[]): void {
if (this._state === 'terminated') {
throw new Error('Worker has been terminated');
}
if (transfer && transfer.length > 0) {
this.worker.postMessage(message, transfer);
} else {
this.worker.postMessage(message);
}
}
public onMessage(handler: (event: { data: any }) => void): void {
this.worker.onmessage = (event: MessageEvent) => {
handler({ data: event.data });
};
}
public onError(handler: (error: ErrorEvent) => void): void {
this.worker.onerror = handler;
}
public terminate(): void {
if (this._state === 'running') {
this.worker.terminate();
URL.revokeObjectURL(this.scriptURL);
this._state = 'terminated';
}
}
}

View File

@@ -179,7 +179,7 @@ export interface PlatformDetectionResult {
/**
* 平台类型
*/
platform: 'browser' | 'wechat-minigame' | 'bytedance-minigame' | 'alipay-minigame' | 'baidu-minigame' | 'unknown';
platform: 'browser' | 'wechat-minigame' | 'bytedance-minigame' | 'alipay-minigame' | 'baidu-minigame' | 'nodejs' | 'unknown';
/**
* 是否确定检测结果
@@ -197,93 +197,3 @@ export interface PlatformDetectionResult {
adapterClass?: string;
}
/**
* 微信小游戏设备信息接口
*/
export interface WeChatDeviceInfo {
// 设备基础信息
brand?: string;
model?: string;
platform?: string;
system?: string;
benchmarkLevel?: number;
cpuType?: string;
memorySize?: string;
deviceAbi?: string;
abi?: string;
// 窗口信息
screenWidth?: number;
screenHeight?: number;
screenTop?: number;
windowWidth?: number;
windowHeight?: number;
pixelRatio?: number;
statusBarHeight?: number;
safeArea?: {
top: number;
bottom: number;
left: number;
right: number;
width: number;
height: number;
};
// 应用信息
version?: string;
language?: string;
theme?: string;
SDKVersion?: string;
enableDebug?: boolean;
fontSizeSetting?: number;
host?: {
appId: string;
};
}
/**
* 浏览器设备信息接口
*/
export interface BrowserDeviceInfo {
// 浏览器信息
userAgent?: string;
vendor?: string;
language?: string;
languages?: string[];
cookieEnabled?: boolean;
onLine?: boolean;
doNotTrack?: string | null;
// 硬件信息
hardwareConcurrency?: number;
deviceMemory?: number;
maxTouchPoints?: number;
// 屏幕信息
screenWidth?: number;
screenHeight?: number;
availWidth?: number;
availHeight?: number;
colorDepth?: number;
pixelDepth?: number;
// 窗口信息
innerWidth?: number;
innerHeight?: number;
outerWidth?: number;
outerHeight?: number;
devicePixelRatio?: number;
// 连接信息(如果支持)
connection?: {
effectiveType?: string;
downlink?: number;
rtt?: number;
saveData?: boolean;
};
// 平台信息
platform?: string;
appVersion?: string;
appName?: string;
}

View File

@@ -27,8 +27,15 @@ export class PlatformDetector {
features.push('self');
}
// 检测Node.js环境优先级最高因为Node.js可能包含全局对象模拟
if (this.isNodeJS()) {
platform = 'nodejs';
confident = true;
adapterClass = 'NodeAdapter';
features.push('nodejs', 'process', 'require');
}
// 检测微信小游戏环境
if (this.isWeChatMiniGame()) {
else if (this.isWeChatMiniGame()) {
platform = 'wechat-minigame';
confident = true;
adapterClass = 'WeChatMiniGameAdapter';
@@ -122,6 +129,28 @@ export class PlatformDetector {
return false;
}
/**
* 检测是否为Node.js环境
*/
private static isNodeJS(): boolean {
try {
// 检查Node.js特有的全局对象和模块
return !!(
typeof process !== 'undefined' &&
process.versions &&
process.versions.node &&
typeof require !== 'undefined' &&
typeof module !== 'undefined' &&
typeof exports !== 'undefined' &&
// 确保不是在浏览器环境中的Node.js模拟
typeof window === 'undefined' &&
typeof document === 'undefined'
);
} catch {
return false;
}
}
/**
* 检测是否为支付宝小游戏环境
*/

View File

@@ -1,22 +1,17 @@
import type { IPlatformAdapter } from './IPlatformAdapter';
import { PlatformDetector } from './PlatformDetector';
import { BrowserAdapter } from './BrowserAdapter';
import { WeChatMiniGameAdapter } from './WeChatMiniGameAdapter';
import { createLogger, type ILogger } from '../Utils/Logger';
/**
* 平台管理器
* 负责自动检测平台并提供对应的适配器
* 用户需要手动注册平台适配器
*/
export class PlatformManager {
private static instance: PlatformManager;
private adapter: IPlatformAdapter | null = null;
private detectionResult: any = null;
private readonly logger: ILogger;
private constructor() {
this.logger = createLogger('PlatformManager');
this.detectAndInitialize();
}
/**
@@ -34,106 +29,42 @@ export class PlatformManager {
*/
public getAdapter(): IPlatformAdapter {
if (!this.adapter) {
throw new Error('平台适配器未初始化,请检查平台环境');
throw new Error('平台适配器未注册,请调用 registerAdapter() 注册适配器');
}
return this.adapter;
}
/**
* 获取平台检测结果
* 注册平台适配器
*/
public getDetectionResult() {
return this.detectionResult;
}
/**
* 手动设置适配器(用于测试或特殊情况)
*/
public setAdapter(adapter: IPlatformAdapter): void {
public registerAdapter(adapter: IPlatformAdapter): void {
this.adapter = adapter;
}
/**
* 检测平台并初始化对应的适配器
*/
private detectAndInitialize(): void {
this.detectionResult = PlatformDetector.detect();
try {
switch (this.detectionResult.platform) {
case 'wechat-minigame':
this.adapter = new WeChatMiniGameAdapter();
break;
case 'bytedance-minigame':
// TODO: 实现字节跳动小游戏适配器
this.logger.warn('字节跳动小游戏适配器尚未实现,降级到浏览器适配器');
this.adapter = new BrowserAdapter();
break;
case 'alipay-minigame':
// TODO: 实现支付宝小游戏适配器
this.logger.warn('支付宝小游戏适配器尚未实现,降级到浏览器适配器');
this.adapter = new BrowserAdapter();
break;
case 'baidu-minigame':
// TODO: 实现百度小游戏适配器
this.logger.warn('百度小游戏适配器尚未实现,降级到浏览器适配器');
this.adapter = new BrowserAdapter();
break;
case 'browser':
default:
this.adapter = new BrowserAdapter();
break;
}
// 输出初始化信息
this.logInitializationInfo();
} catch (error) {
this.logger.error('平台适配器初始化失败:', error);
// 降级到浏览器适配器
this.adapter = new BrowserAdapter();
}
}
/**
* 输出初始化信息
*/
private logInitializationInfo(): void {
if (!this.adapter) return;
const config = this.adapter.getPlatformConfig();
this.logger.info(`平台适配器初始化完成:`, {
platform: this.detectionResult.platform,
adapterName: this.adapter.name,
version: this.adapter.version,
features: this.detectionResult.features,
config: {
maxWorkerCount: config.maxWorkerCount,
supportsSharedArrayBuffer: this.adapter.isSharedArrayBufferSupported(),
supportsWorker: this.adapter.isWorkerSupported(),
hardwareConcurrency: this.adapter.getHardwareConcurrency()
}
this.logger.info(`平台适配器已注册: ${adapter.name}`, {
name: adapter.name,
version: adapter.version,
supportsWorker: adapter.isWorkerSupported(),
supportsSharedArrayBuffer: adapter.isSharedArrayBufferSupported(),
hardwareConcurrency: adapter.getHardwareConcurrency()
});
}
/**
* 获取详细的平台信息(用于调试)
* 检查是否已注册适配器
*/
public getDetailedInfo(): any {
return {
detectionResult: this.detectionResult,
detailedInfo: PlatformDetector.getDetailedInfo(),
adapterInfo: this.adapter ? {
name: this.adapter.name,
version: this.adapter.version,
config: this.adapter.getPlatformConfig()
} : null
};
public hasAdapter(): boolean {
return this.adapter !== null;
}
/**
* 获取平台适配器信息(用于调试)
*/
public getAdapterInfo(): any {
return this.adapter ? {
name: this.adapter.name,
version: this.adapter.version,
config: this.adapter.getPlatformConfig()
} : null;
}
/**
@@ -192,7 +123,7 @@ export class PlatformManager {
*/
public async getFullPlatformConfig(): Promise<any> {
if (!this.adapter) {
return null;
throw new Error('平台适配器未注册');
}
// 如果适配器支持异步获取配置,使用异步方法

View File

@@ -1,451 +0,0 @@
/// <reference types="minigame-api-typings" />
import type {
IPlatformAdapter,
PlatformWorker,
WorkerCreationOptions,
PlatformConfig,
WeChatDeviceInfo
} from './IPlatformAdapter';
import { createLogger, type ILogger } from '../Utils/Logger';
/**
* 微信小游戏平台适配器
* 适配微信小游戏环境的特殊限制和API
*/
export class WeChatMiniGameAdapter implements IPlatformAdapter {
public readonly name = 'wechat-minigame';
public readonly version = this.getWeChatVersion();
private readonly wx: WechatMinigame.Wx;
private readonly logger: ILogger;
constructor() {
this.logger = createLogger('WeChatMiniGameAdapter');
this.wx = (globalThis as any).wx;
if (!this.wx) {
throw new Error('微信小游戏环境未检测到wx对象');
}
}
/**
* 检查是否支持Worker
* 微信小游戏虽然有Worker API但限制太严格对于动态ECS系统不实用
*/
public isWorkerSupported(): boolean {
// 虽然微信小游戏有Worker API但由于以下限制实际上不适用于动态ECS系统
// 1. 不能动态创建Worker脚本必须预配置文件
// 2. 禁止eval不能动态执行用户的处理函数
// 3. 需要用户手动配置game.json
// 因此对于WorkerEntitySystem来说认为不支持Worker
return false;
}
/**
* 检查是否支持SharedArrayBuffer
* 微信小游戏不支持SharedArrayBuffer因为
* 1. 不满足crossOriginIsolated要求
* 2. 小游戏运行在受限沙箱环境中
* 3. 出于安全考虑微信限制了此API
*/
public isSharedArrayBufferSupported(): boolean {
// 微信小游戏明确不支持SharedArrayBuffer
// 即使有API存在也无法在沙箱环境中正常使用
return false;
}
/**
* 获取硬件并发数
* 微信小游戏没有直接的CPU核心数API返回保守的默认值
* 用户应该根据自己的业务需求和测试结果来设置Worker数量
*/
public getHardwareConcurrency(): number {
// 微信小游戏平台返回保守的默认值
// 用户可以通过getDevicePerformanceInfo()获取详细信息来自行判断
return 4;
}
/**
* 获取设备性能信息(供用户参考)
* 用户可以根据这些信息自行决定Worker配置
*/
public getDevicePerformanceInfo(): Promise<{
benchmarkLevel?: number;
modelLevel?: number;
memorySize?: string;
cpuType?: string;
platform?: string;
system?: string;
}> {
return new Promise((resolve) => {
const result: any = {};
// 获取设备基础信息
if (typeof this.wx.getDeviceInfo === 'function') {
try {
const deviceInfo = this.wx.getDeviceInfo();
Object.assign(result, {
memorySize: deviceInfo.memorySize,
cpuType: deviceInfo.cpuType,
platform: deviceInfo.platform,
system: deviceInfo.system,
benchmarkLevel: deviceInfo.benchmarkLevel
});
} catch (error) {
this.logger.warn('获取设备信息失败', error);
}
}
// 获取性能基准信息
if (typeof this.wx.getDeviceBenchmarkInfo === 'function') {
this.wx.getDeviceBenchmarkInfo({
success: (res) => {
result.benchmarkLevel = res.benchmarkLevel;
result.modelLevel = res.modelLevel;
resolve(result);
},
fail: () => {
resolve(result);
}
});
} else {
resolve(result);
}
});
}
/**
* 创建Worker
* 微信小游戏不支持WorkerEntitySystem所需的动态Worker创建
*/
public createWorker(_script: string, _options: WorkerCreationOptions = {}): PlatformWorker {
throw new Error(
'微信小游戏不支持WorkerEntitySystem。' +
'原因1) 不能动态创建Worker脚本 2) 禁止eval动态执行代码。' +
'WorkerEntitySystem将自动降级到同步模式运行。'
);
}
/**
* 从预配置的文件路径创建Worker仅供特殊用途
* 注意这不适用于WorkerEntitySystem仅供其他特殊Worker需求使用
*/
public createWorkerFromPath(scriptPath: string, options: {
useExperimentalWorker?: boolean;
name?: string;
} = {}): PlatformWorker {
// 即使支持原生Worker API也明确说明不适用于ECS
this.logger.warn('微信小游戏Worker不适用于WorkerEntitySystem建议使用同步模式');
return new WeChatWorker(scriptPath, options, this.wx);
}
/**
* 创建SharedArrayBuffer
* 微信小游戏通常不支持返回null
*/
public createSharedArrayBuffer(length: number): SharedArrayBuffer | null {
if (!this.isSharedArrayBufferSupported()) {
this.logger.info('微信小游戏环境不支持SharedArrayBuffer将使用Worker模式');
return null;
}
try {
return new SharedArrayBuffer(length);
} catch (error) {
this.logger.warn('SharedArrayBuffer创建失败', error);
return null;
}
}
/**
* 获取高精度时间戳
*/
public getHighResTimestamp(): number {
// 微信小游戏支持performance.now()
if (typeof performance !== 'undefined' && performance.now) {
return performance.now();
}
// 备选方案使用Date.now()
return Date.now();
}
/**
* 获取平台配置(同步版本,不包含异步获取的性能信息)
*/
public getPlatformConfig(): PlatformConfig {
return {
maxWorkerCount: 0, // 不支持WorkerEntitySystem
supportsModuleWorker: false,
supportsTransferableObjects: false, // 对WorkerEntitySystem无意义
maxSharedArrayBufferSize: 0, // 不支持SharedArrayBuffer
workerScriptPrefix: '',
limitations: {
noEval: true, // 微信小游戏禁止eval
requiresWorkerInit: true,
// 明确说明Worker限制
workerNotSupported: true,
workerLimitations: [
'不能动态创建Worker脚本',
'禁止eval动态执行代码',
'必须预配置Worker文件路径',
'不适用于动态ECS系统'
]
},
extensions: {
wechatVersion: this.version,
supportedAPIs: this.getSupportedAPIs(),
deviceInfo: this.getDeviceInfo()
}
};
}
/**
* 异步获取平台配置(包含性能信息)
*/
public async getPlatformConfigAsync(): Promise<PlatformConfig> {
const baseConfig = this.getPlatformConfig();
try {
// 异步获取性能信息
const performanceInfo = await this.getDevicePerformanceInfo();
return {
...baseConfig,
extensions: {
...baseConfig.extensions,
performanceInfo
}
};
} catch (error) {
this.logger.warn('获取性能信息失败,返回基础配置', error);
return baseConfig;
}
}
/**
* 获取微信版本信息
*/
private getWeChatVersion(): string {
try {
const systemInfo = this.wx.getSystemInfoSync();
return `WeChat ${systemInfo.version} (${systemInfo.platform})`;
} catch {
return 'WeChat Unknown';
}
}
/**
* 获取支持的API列表
*/
private getSupportedAPIs(): string[] {
const apis: string[] = [];
// 检查常用的微信小游戏API
const commonAPIs = [
'getSystemInfo', 'createCanvas', 'createImage', 'createAudio',
'createWorker', 'downloadFile', 'request', 'connectSocket',
'setStorage', 'getStorage', 'showToast', 'showModal'
];
for (const api of commonAPIs) {
if (typeof (this.wx as any)[api] === 'function') {
apis.push(api);
}
}
return apis;
}
/**
* 获取设备信息
*/
public getDeviceInfo(): WeChatDeviceInfo {
try {
const deviceInfo: any = {};
// 优先使用最新的设备信息API
if (typeof this.wx.getDeviceInfo === 'function') {
const info = this.wx.getDeviceInfo();
Object.assign(deviceInfo, {
brand: info.brand,
model: info.model,
platform: info.platform,
system: info.system,
benchmarkLevel: info.benchmarkLevel,
cpuType: info.cpuType,
memorySize: info.memorySize,
deviceAbi: info.deviceAbi,
abi: info.abi
});
}
// 获取设备性能基准信息
if (typeof this.wx.getDeviceBenchmarkInfo === 'function') {
this.wx.getDeviceBenchmarkInfo({
success: (res) => {
deviceInfo.benchmarkLevel = res.benchmarkLevel;
deviceInfo.modelLevel = res.modelLevel;
}
});
}
// 获取窗口信息
if (typeof this.wx.getWindowInfo === 'function') {
const windowInfo = this.wx.getWindowInfo();
Object.assign(deviceInfo, {
screenWidth: windowInfo.screenWidth,
screenHeight: windowInfo.screenHeight,
screenTop: windowInfo.screenTop,
windowWidth: windowInfo.windowWidth,
windowHeight: windowInfo.windowHeight,
pixelRatio: windowInfo.pixelRatio,
statusBarHeight: windowInfo.statusBarHeight,
safeArea: windowInfo.safeArea
});
}
// 获取应用基础信息
if (typeof this.wx.getAppBaseInfo === 'function') {
try {
const appInfo = this.wx.getAppBaseInfo();
Object.assign(deviceInfo, {
version: appInfo.version,
language: appInfo.language,
theme: appInfo.theme,
SDKVersion: appInfo.SDKVersion,
enableDebug: appInfo.enableDebug,
fontSizeSetting: appInfo.fontSizeSetting,
// host是一个对象不是hostName
host: appInfo.host
});
} catch (error) {
this.logger.warn('获取应用基础信息失败', error);
}
}
// 如果新API不完整才使用废弃API作为兜底
if (Object.keys(deviceInfo).length === 0 && typeof this.wx.getSystemInfoSync === 'function') {
this.logger.warn('新API不可用使用废弃的getSystemInfoSync作为兜底');
try {
const systemInfo = this.wx.getSystemInfoSync();
return {
brand: systemInfo.brand,
model: systemInfo.model,
platform: systemInfo.platform,
system: systemInfo.system,
version: systemInfo.version,
benchmarkLevel: systemInfo.benchmarkLevel,
screenWidth: systemInfo.screenWidth,
screenHeight: systemInfo.screenHeight,
pixelRatio: systemInfo.pixelRatio
} as WeChatDeviceInfo;
} catch (error) {
this.logger.error('所有获取设备信息的方法都失败了', error);
return {} as WeChatDeviceInfo;
}
}
return deviceInfo as WeChatDeviceInfo;
} catch (error) {
this.logger.warn('获取设备信息失败', error);
return {} as WeChatDeviceInfo;
}
}
}
/**
* 微信小游戏Worker封装
*/
class WeChatWorker implements PlatformWorker {
private _state: 'running' | 'terminated' = 'running';
private worker!: WechatMinigame.Worker;
private readonly logger: ILogger;
constructor(
private scriptPath: string,
private options: { useExperimentalWorker?: boolean; name?: string },
private wx: WechatMinigame.Wx
) {
this.logger = createLogger('WeChatWorker');
this.createWeChatWorker();
}
public get state(): 'running' | 'terminated' {
return this._state;
}
public postMessage(message: any, _transfer?: Transferable[]): void {
if (this._state === 'terminated') {
throw new Error('Worker已被终止');
}
if (this.worker) {
this.worker.postMessage(message);
}
}
public onMessage(handler: (event: { data: any }) => void): void {
if (this.worker) {
this.worker.onMessage((data: any) => {
handler({ data });
});
}
}
public onError(handler: (error: ErrorEvent) => void): void {
if (this.worker) {
this.worker.onError((error: any) => {
// 转换微信错误格式为标准ErrorEvent格式
const errorEvent = new ErrorEvent('error', {
message: error.message || '微信Worker错误',
filename: error.filename || '',
lineno: error.lineno || 0,
colno: error.colno || 0,
error: error
});
handler(errorEvent);
});
}
}
public terminate(): void {
if (this._state === 'running' && this.worker) {
this.worker.terminate();
this._state = 'terminated';
}
}
/**
* 创建微信Worker
* 使用预配置的Worker脚本文件路径
*/
private createWeChatWorker(): void {
try {
// 使用微信小游戏的createWorker API传入预配置的脚本路径
this.worker = this.wx.createWorker(this.scriptPath, {
useExperimentalWorker: this.options.useExperimentalWorker || false
});
// 监听Worker被系统回收事件实验性Worker特有
if (this.options.useExperimentalWorker && this.worker.onProcessKilled) {
this.worker.onProcessKilled(() => {
this.logger.warn(`微信Worker ${this.scriptPath} 被系统回收`);
this._state = 'terminated';
});
}
} catch (error) {
this.logger.error('创建微信Worker失败:', error);
throw new Error(
`无法创建微信Worker: ${error}` +
`请确保已在game.json中配置workers字段并且Worker文件 ${this.scriptPath} 存在。`
);
}
}
}

View File

@@ -8,9 +8,7 @@ export type {
PlatformWorker,
WorkerCreationOptions,
PlatformConfig,
PlatformDetectionResult,
WeChatDeviceInfo,
BrowserDeviceInfo
PlatformDetectionResult
} from './IPlatformAdapter';
// 平台检测器
@@ -19,16 +17,13 @@ export { PlatformDetector } from './PlatformDetector';
// 平台管理器
export { PlatformManager } from './PlatformManager';
// 平台适配器实现
export { BrowserAdapter } from './BrowserAdapter';
export { WeChatMiniGameAdapter } from './WeChatMiniGameAdapter';
// 内部导入用于便利函数
import { PlatformManager } from './PlatformManager';
import type { IPlatformAdapter } from './IPlatformAdapter';
// 便利函数
export function getCurrentPlatform() {
return PlatformManager.getInstance().getDetectionResult();
export function registerPlatformAdapter(adapter: IPlatformAdapter) {
return PlatformManager.getInstance().registerAdapter(adapter);
}
export function getCurrentAdapter() {
@@ -45,4 +40,8 @@ export function getFullPlatformConfig() {
export function supportsFeature(feature: 'worker' | 'shared-array-buffer' | 'transferable-objects' | 'module-worker') {
return PlatformManager.getInstance().supportsFeature(feature);
}
export function hasAdapter() {
return PlatformManager.getInstance().hasAdapter();
}