From b7a35b05c0f84541cdd5f2c17b8b327acef6a068 Mon Sep 17 00:00:00 2001 From: gongxh Date: Fri, 18 Apr 2025 17:51:42 +0800 Subject: [PATCH] =?UTF-8?q?=E7=83=AD=E6=9B=B4=E6=96=B0=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hotupdate/HotUpdateManager.ts | 452 ++++++++++++++-------- src/interface/PromiseResult.ts | 19 + src/kunpocc.ts | 6 +- src/minigame/bytedance/BytedanceCommon.ts | 5 +- src/net/http/IHttpEvent.ts | 2 +- src/net/nettools/ReadNetFile.ts | 29 ++ src/tool/Utils.ts | 11 + 7 files changed, 353 insertions(+), 171 deletions(-) create mode 100644 src/interface/PromiseResult.ts create mode 100644 src/net/nettools/ReadNetFile.ts diff --git a/src/hotupdate/HotUpdateManager.ts b/src/hotupdate/HotUpdateManager.ts index 32c89e3..8faf6ed 100644 --- a/src/hotupdate/HotUpdateManager.ts +++ b/src/hotupdate/HotUpdateManager.ts @@ -4,11 +4,52 @@ * @Description: 热更新管理器 */ -import { Asset, game, native, sys } from "cc"; +import { game, native, sys } from "cc"; import { Platform } from "../global/Platform"; -import { log, warn } from "../tool/log"; +import { ICheckUpdatePromiseResult, IPromiseResult } from "../interface/PromiseResult"; +import { ReadNetFile } from "../net/nettools/ReadNetFile"; +import { debug, log } from "../tool/log"; import { Utils } from "../tool/Utils"; +interface IHotUpdateConfig { + packageUrl: string; + remoteManifestUrl: string; + remoteVersionUrl: string; +} + +export enum HotUpdateCode { + /** 成功 */ + SUCCEED = 0, + /** 重复初始化 */ + REPEAT_INIT = -1001, + /** 平台不支持 不需要热更新 */ + PLATFORM_NOT_SUPPORTED = -1002, + /** 未初始化 */ + NOT_INITIALIZED = -1003, + /** 更新中 */ + UPDATING = -1004, + + /** 加载本地manifest失败 */ + LOAD_LOCAL_MANIFEST_FAILED = -1005, + /** 下载manifest文件失败 */ + DOWNLOAD_MANIFEST_FAILED = -1006, + /** 解析manifest文件失败 */ + PARSE_MANIFEST_FAILED = -1007, + + /** 更新失败 需要重试 */ + UPDATE_FAILED = -1008, + /** 更新错误 */ + UPDATE_ERROR = -1009, + /** 解压错误 */ + DECOMPRESS_ERROR = -1010, + + /** 下载 hotconfig 文件失败 */ + DOWNLOAD_HOTCONFIG_FAILED = -1011, + + /** 解析 hotconfig 文件失败 */ + PARSE_HOTCONFIG_FAILED = -1012, +} + const TAG = "hotupdate:"; export class HotUpdateManager { @@ -19,7 +60,10 @@ export class HotUpdateManager { } return HotUpdateManager.instance; } - + /** 本地manifest路径 */ + private _manifestUrl: string = ''; + /** 热更新配置路径 (可选) 用来动态替换manifest文件中关联的地址 */ + private _hotconfigUrl: string = ''; /** 版本号 */ private _version: string = ''; /** 可写路径 */ @@ -29,112 +73,268 @@ export class HotUpdateManager { /** 是否正在更新 或者 正在检查更新 */ private _updating: boolean = false; - /** 检查更新的回调 */ - private _checkSucceed: (need: boolean, size: number) => void = null; - private _checkFail: (code: number, message: string) => void = null; - /** 更新回调 */ - private _updateProgress: (kb: number, total: number) => void = null; - private _updateFail: (code: number, message: string) => void = null; - private _updateError: (code: number, message: string) => void = null; + private _updateProgress: (kb: number, total: number) => void = null; // 更新进度 + private _updateFail: (res: IPromiseResult) => void = null; // 更新失败 + private _finish: (res: IPromiseResult) => void = null; // 更新结束 + + /** + * 获取资源版本号, 须初始化成功后再使用 + * @return 资源版本号 默认值 ‘0’ + */ + public get resVersion(): string { + return this._am?.getLocalManifest()?.getVersion() || "0"; + } + /** * 1. 初始化热更新管理器 - * @param manifest 传入manifest文件 + * @param manifestUrl 传入本地manifest文件地址 资源的assets.nativeUrl * @param version 传入游戏版本号 eg: 1.0.0 + * @param hotconfigUrl 传入热更新配置地址 用于替换manifest文件中关联的地址 */ - public init(manifest: Asset, version: string): void { - if (!Platform.isNativeMobile) { - return; - } - if (this._am) { - warn(`${TAG}请勿重复初始化`); - return; - } - this._version = version; + public init(manifestUrl: string, version: string, hotconfigUrl?: string): Promise { + return new Promise((resolve, reject) => { + if (!Platform.isNativeMobile) { + reject({ code: HotUpdateCode.PLATFORM_NOT_SUPPORTED, message: "当前平台不支持热更新" }); + } + if (this._am) { + reject({ code: HotUpdateCode.REPEAT_INIT, message: "请勿重复初始化" }); + } + this._manifestUrl = manifestUrl; + this._hotconfigUrl = hotconfigUrl || ''; + this._version = version; - let writablePath = native?.fileUtils?.getWritablePath() || ""; - if (!writablePath.endsWith("/")) { - writablePath += "/"; - } - this._writablePath = `${writablePath}hot-update/${version}/`; - log(`${TAG}可写路径:${this._writablePath}`); + let writablePath = native?.fileUtils?.getWritablePath() || ""; + if (!writablePath.endsWith("/")) { + writablePath += "/"; + } + this._writablePath = `${writablePath}hot-update/${version}/`; + log(`${TAG}可写路径:${this._writablePath}`); - // 创建 am 对象 - this._am = native.AssetsManager.create("", this._writablePath); - this._am.setVersionCompareHandle(Utils.compareVersion); - this._am.setVerifyCallback(this._verifyCallback); - // 加载本地的 manifest - log(`${TAG} 加载本地的 manifest:${manifest.nativeUrl}`); - this._am.loadLocalManifest(manifest.nativeUrl); + // 创建 am 对象 + this._am = native.AssetsManager.create("", this._writablePath); + this._am.setVersionCompareHandle(Utils.compareVersion); + this._am.setVerifyCallback(this._verifyCallback); + // 加载本地的 manifest + log(`${TAG} 加载本地的 manifest:${manifestUrl}`); + if (this._am.loadLocalManifest(manifestUrl)) { + resolve({ code: HotUpdateCode.SUCCEED, message: "初始化成功" }); + } else { + reject({ code: HotUpdateCode.LOAD_LOCAL_MANIFEST_FAILED, message: "加载本地manifest失败" }); + } + }); + } + + /** 加载远程的hotconfig文件 并替换local manifest内容 */ + private loadRemoteHotConfig(): Promise { + return new Promise((resolve, reject) => { + new ReadNetFile({ + url: this._hotconfigUrl, + timeout: 5, + responseType: "text", + onComplete: (data: string) => { + log(`${TAG} 下载hotconfig文件成功`); + if (Utils.isJsonString(data)) { + let hotconfig: IHotUpdateConfig = JSON.parse(data); + let content = native.fileUtils.getStringFromFile(this._manifestUrl); // 这个一定有 + // 使用拿到的cdn上的配置,修改本地manifest内容 + let newManifest: IHotUpdateConfig = JSON.parse(content); + + newManifest.remoteManifestUrl = hotconfig.remoteManifestUrl; + newManifest.remoteVersionUrl = hotconfig.remoteVersionUrl; + newManifest.packageUrl = hotconfig.packageUrl; + // 注册本地manifest根目录 + let manifestRoot = ""; + let found = this._manifestUrl.lastIndexOf("/"); + if (found === -1) { + found = this._manifestUrl.lastIndexOf("\\"); + } + if (found !== -1) { + manifestRoot = this._manifestUrl.substring(0, found + 1); + } + this._am.getLocalManifest().parseJSONString(JSON.stringify(newManifest), manifestRoot); + // log(TAG + "manifest root:" + this._am.getLocalManifest().getManifestRoot()); + // log(TAG + "manifest packageUrl:" + this._am.getLocalManifest().getPackageUrl()); + // log(TAG + "manifest version:" + this._am.getLocalManifest().getVersion()); + // log(TAG + "manifest versionFileUrl:" + this._am.getLocalManifest().getVersionFileUrl()); + // log(TAG + "manifest manifestFileUrl:" + this._am.getLocalManifest().getManifestFileUrl()); + // 重新加载本地manifest + resolve({ code: HotUpdateCode.SUCCEED, message: "更新热更新配置成功" }); + } else { + log(`${TAG} hotconfig.manifest文件格式错误`); + resolve({ code: HotUpdateCode.PARSE_HOTCONFIG_FAILED, message: "hotconfig.manifest文件格式错误" }); + } + }, + onError: (code: number, message: string) => { + log(`${TAG} 下载hotconfig.manifest文件失败`, code, message); + // 下载hotconfig.manifest文件失败 + resolve({ code: HotUpdateCode.DOWNLOAD_HOTCONFIG_FAILED, message: "下载hotconfig.manifest文件失败" }); + } + }); + }) } /** - * 2. 检查是否有新的热更版本 - * @param res.succeed.need 是否需要更新 - * @param res.succeed.size 需要更新的资源大小 (KB) - * - * @param res.fail 检查失败的回调 - * @param res.fail.code - * -1000: 未初始化 - * -1001: 正在更新或者正在检查更新 - * -1002: 本地manifest文件错误 - * -1004: 解析远程manifest文件失败 + * 检查是否存在热更新 + * 提供一个对外的方法检查是否存在热更新 + * @return {Promise} */ - public checkUpdate(res: { succeed: (need: boolean, size: number) => void, fail: (code: number, message: string) => void }): void { - this._checkSucceed = res.succeed; - this._checkFail = res.fail; - if (this._updating) { - res.fail(-1001, "正在更新或者正在检查更新"); - return; - } - if (!Platform.isNativeMobile) { - res.succeed(false, 0); - return; - } - if (!this._am) { - res.fail(-1000, "未初始化, 需要先调用init方法"); - return; - } - this._updating = true; - // 设置回调 - this._am.setEventCallback(this._checkCb.bind(this)); - // 检查更新 - this._am.checkUpdate(); + public checkUpdate(): Promise { + return new Promise((resolve, reject) => { + if (!Platform.isNativeMobile) { + reject({ code: HotUpdateCode.PLATFORM_NOT_SUPPORTED, message: "当前平台不需要热更新" }); + return; + } + if (!this._am) { + reject({ code: HotUpdateCode.NOT_INITIALIZED, message: "未初始化, 需要先调用init方法" }); + return; + } + if (this._updating) { + reject({ code: HotUpdateCode.UPDATING, message: "正在更新或者正在检查更新" }); + return; + } + this._updating = true; + // 设置回调 + this._am.setEventCallback((event: native.EventAssetsManager) => { + let eventCode = event.getEventCode(); + log(`${TAG} 检查更新回调code:${eventCode}`); + this._updating = false; + switch (eventCode) { + case native.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST: + this._am.setEventCallback(null); + this._updating = false; + resolve({ code: HotUpdateCode.DOWNLOAD_MANIFEST_FAILED, message: "下载manifest文件失败", needUpdate: false, size: 0 }); + return; + case native.EventAssetsManager.ERROR_PARSE_MANIFEST: + this._am.setEventCallback(null); + this._updating = false; + resolve({ code: HotUpdateCode.PARSE_MANIFEST_FAILED, message: "解析manifest文件失败", needUpdate: false, size: 0 }); + return; + case native.EventAssetsManager.ALREADY_UP_TO_DATE: + this._am.setEventCallback(null); + this._updating = false; + resolve({ code: HotUpdateCode.SUCCEED, message: "已是最新版本", needUpdate: false, size: 0 }); + return; + case native.EventAssetsManager.NEW_VERSION_FOUND: + // 发现新版本 + this._am.setEventCallback(null); + this._updating = false; + resolve({ code: HotUpdateCode.SUCCEED, message: "发现新版本", needUpdate: true, size: this._am.getTotalBytes() / 1024 }); + return; + } + }); + + // 如果存在替换地址 + if (this._hotconfigUrl) { + log(`${TAG} 下载 hotconfig 文件`); + this.loadRemoteHotConfig().then((res) => { + if (res.code === HotUpdateCode.SUCCEED || res.code === HotUpdateCode.DOWNLOAD_HOTCONFIG_FAILED) { + this._am.checkUpdate(); + } else { + this._updating = false; + reject(res); + } + }); + } else { + // 使用本地的menifest检查更新 + log(`${TAG} 使用本地的menifest检查更新`); + this._am.checkUpdate(); + } + }); } /** - * 3. 开始热更新 + * 开始热更新 * @param res.progress 更新进度回调 kb: 已下载的资源大小, total: 总资源大小 (kb) - * @param res.fail 更新失败 可以重试 - * @param res.fail.code 更新失败错误码 - * -10001: 更新失败 需要重试 - * @param res.error 更新错误 无法重试 - * @param res.error.code 更新错误错误码 - * -1000: 未初始化 - * -1001: 正在更新或者正在检查更新 - * -10002: 资源更新错误 - * -10003: 解压错误 + * @param res.fail 更新失败了 等待重试 + * @param res.finish 更新结束了 根据code 判断是否跳过 */ public startUpdate(res: { progress: (kb: number, total: number) => void, - fail: (code: number, message: string) => void, - error: (code: number, message: string) => void + fail: (res: IPromiseResult) => void, + finish: (res: IPromiseResult) => void }): void { - this._updateProgress = res.progress; - this._updateFail = res.fail; - this._updateError = res.error; - - log(`${TAG} 开始热更新`); - if (this._updating) { - res.error(-1001, "正在更新或者正在检查更新"); - return; + if (!Platform.isNativeMobile) { + res.finish({ code: HotUpdateCode.PLATFORM_NOT_SUPPORTED, message: "当前平台不需要热更新" }); } if (!this._am) { - res.error(-1000, "未初始化, 需要先调用init方法"); + res.finish({ code: HotUpdateCode.NOT_INITIALIZED, message: "未初始化, 需要先调用init方法" }); return; } + if (this._updating) { + res.finish({ code: HotUpdateCode.UPDATING, message: "正在更新或者正在检查更新" }); + return; + } + this._updateProgress = res.progress; + this._updateFail = res.fail; + this._finish = res.finish; + + log(`${TAG} 开始热更新`); + this.checkUpdate().then((result) => { + if (result.needUpdate) { + this.update(); + } else { + res.finish({ code: HotUpdateCode.SUCCEED, message: "已是最新版本" }); + } + }).catch((err) => { + res.finish({ code: err.code, message: err.message }); + }); + } + + private update(): void { this._updating = true; - this._am.setEventCallback(this._updateCb.bind(this)); + this._am.setEventCallback((event: native.EventAssetsManager) => { + let eventCode = event.getEventCode(); + debug(`${TAG} 更新回调code:${eventCode}`); + switch (eventCode) { + case native.EventAssetsManager.UPDATE_PROGRESSION: { + let bytes = event.getDownloadedBytes() / 1024; + let total = event.getTotalBytes() / 1024; + this._updateProgress(bytes, total); + break; + } + case native.EventAssetsManager.UPDATE_FINISHED: { + this._updating = false; + // 更新完成 自动重启 + this._am.setEventCallback(null); + + // Prepend the manifest's search path + let searchPaths = native.fileUtils.getSearchPaths(); + log(`${TAG} 当前搜索路径:${JSON.stringify(searchPaths)}`); + + let newPaths = this._am.getLocalManifest().getSearchPaths(); + log(`${TAG} 新搜索路径:${JSON.stringify(newPaths)}`); + + Array.prototype.unshift.apply(searchPaths, newPaths); + sys.localStorage.setItem('hotupdate::version', this._version); + sys.localStorage.setItem('hotupdate::searchpaths', JSON.stringify(searchPaths)); + native.fileUtils.setSearchPaths(searchPaths); + + // 重启游戏 + setTimeout(() => { + game.restart(); + }, 500); + break; + } + case native.EventAssetsManager.UPDATE_FAILED: { + this._updating = false; + this._updateFail({ code: HotUpdateCode.UPDATE_FAILED, message: event.getMessage() }); + break; + } + case native.EventAssetsManager.ERROR_UPDATING: { + this._updating = false; + this._finish({ code: HotUpdateCode.UPDATE_ERROR, message: event.getMessage() }); + break; + } + case native.EventAssetsManager.ERROR_DECOMPRESS: { + this._updating = false; + this._finish({ code: HotUpdateCode.DECOMPRESS_ERROR, message: event.getMessage() }); + break; + } + default: + break; + } + }); this._am.update(); } @@ -143,87 +343,7 @@ export class HotUpdateManager { this._am.downloadFailedAssets(); } - /** 检查更新的回调 */ - private _checkCb(event: native.EventAssetsManager) { - let eventCode = event.getEventCode(); - log(`${TAG} 检查更新回调code:${eventCode}`); - this._updating = false; - switch (eventCode) { - case native.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST: - this._checkFail(-1002, "本地没有manifest文件"); - break; - case native.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST: - // this._checkFail(-1003, "下载manifest文件失败"); - this._checkSucceed(false, 0); - break; - case native.EventAssetsManager.ERROR_PARSE_MANIFEST: - this._checkFail(-1004, "解析远程manifest文件失败"); - break; - case native.EventAssetsManager.ALREADY_UP_TO_DATE: - this._checkSucceed(false, 0); - break; - case native.EventAssetsManager.NEW_VERSION_FOUND: - // 发现新版本 - this._checkSucceed(true, this._am.getTotalBytes() / 1024); - break; - default: - return; - } - this._am.setEventCallback(null); - } - - /** 更新的回调 */ - private _updateCb(event: native.EventAssetsManager) { - let eventCode = event.getEventCode(); - log(`${TAG} 更新回调code:${eventCode}`); - let needRestart = false; - switch (eventCode) { - case native.EventAssetsManager.UPDATE_PROGRESSION: - let bytes = event.getDownloadedBytes() / 1024; - let total = event.getTotalBytes() / 1024; - this._updateProgress(bytes, total); - break; - case native.EventAssetsManager.UPDATE_FINISHED: - // 更新完成 自动重启 - needRestart = true; - break; - case native.EventAssetsManager.UPDATE_FAILED: - this._updating = false; - this._updateFail(-10001, event.getMessage()); - break; - case native.EventAssetsManager.ERROR_UPDATING: - this._updating = false; - this._updateError(-10002, event.getMessage()); - break; - case native.EventAssetsManager.ERROR_DECOMPRESS: - this._updating = false; - this._updateError(-10003, event.getMessage()); - break; - default: - break; - } - if (needRestart) { - this._am.setEventCallback(null); - - // Prepend the manifest's search path - let searchPaths = native.fileUtils.getSearchPaths(); - log(`${TAG} 当前搜索路径:${JSON.stringify(searchPaths)}`); - - let newPaths = this._am.getLocalManifest().getSearchPaths(); - log(`${TAG} 新搜索路径:${JSON.stringify(newPaths)}`); - - Array.prototype.unshift.apply(searchPaths, newPaths); - sys.localStorage.setItem('hotupdate::version', this._version); - sys.localStorage.setItem('hotupdate::searchpaths', JSON.stringify(searchPaths)); - native.fileUtils.setSearchPaths(searchPaths); - - // 重启游戏 - setTimeout(() => { - game.restart() - }, 500); - } - } - + /** 验证资源 */ private _verifyCallback(path: string, asset: native.ManifestAsset): boolean { // 资源是否被压缩, 如果压缩我们不需要检查它的md5值 let compressed = asset.compressed; diff --git a/src/interface/PromiseResult.ts b/src/interface/PromiseResult.ts new file mode 100644 index 0000000..241cffe --- /dev/null +++ b/src/interface/PromiseResult.ts @@ -0,0 +1,19 @@ +/** + * @Author: Gongxh + * @Date: 2025-04-18 + * @Description: 通用的 Promise 结果 + */ + +export interface IPromiseResult { + /** 0:成功 其他:失败 */ + code: number; + /** 失败信息 */ + message: string; +} + +export interface ICheckUpdatePromiseResult extends IPromiseResult { + /** 是否需要更新 */ + needUpdate?: boolean; + /** 需要更新的资源大小 (KB) */ + size?: number; +} \ No newline at end of file diff --git a/src/kunpocc.ts b/src/kunpocc.ts index 25f0df2..4d49ecf 100644 --- a/src/kunpocc.ts +++ b/src/kunpocc.ts @@ -4,6 +4,7 @@ export { GlobalTimer } from "./global/GlobalTimer"; export { enableDebugMode, FrameConfig, KUNPO_DEBUG } from "./global/header"; export { Platform, PlatformType } from "./global/Platform"; export { Screen } from "./global/Screen"; +export * from "./interface/PromiseResult"; /** tool */ export { Binary } from "./tool/Binary"; @@ -24,6 +25,9 @@ export { IHttpResponse } from "./net/http/IHttpResponse"; /** Socket */ export { Socket } from "./net/socket/Socket"; +/** 读取网络文件 */ +export { ReadNetFile } from "./net/nettools/ReadNetFile"; + /** 四叉树 */ export { Box } from "./quadtree/Box"; export { Circle } from "./quadtree/Circle"; @@ -78,7 +82,7 @@ export { ConditionAnyNode } from "./condition/node/ConditionAnyNode"; export { ConditionBase } from "./condition/node/ConditionBase"; /** 热更新 */ -export { HotUpdateManager } from "./hotupdate/HotUpdateManager"; +export { HotUpdateCode, HotUpdateManager } from "./hotupdate/HotUpdateManager"; /** 小游戏 */ export { AlipayCommon } from "./minigame/alipay/AlipayCommon"; diff --git a/src/minigame/bytedance/BytedanceCommon.ts b/src/minigame/bytedance/BytedanceCommon.ts index b40563d..14b02b8 100644 --- a/src/minigame/bytedance/BytedanceCommon.ts +++ b/src/minigame/bytedance/BytedanceCommon.ts @@ -4,7 +4,6 @@ * @Description: 字节跳动小游戏工具类 */ -import { LaunchParams } from "@douyin-microapp/typings/types/app"; import { warn } from "../../tool/log"; import { IMiniCommon } from "../interface/IMiniCommon"; @@ -24,14 +23,14 @@ export class BytedanceCommon implements IMiniCommon { /** * 获取冷启动参数 */ - public getLaunchOptions(): LaunchParams { + public getLaunchOptions(): BytedanceMiniprogram.LaunchParams { return this._launchOptions; } /** * 获取热启动参数 */ - public getHotLaunchOptions(): LaunchParams { + public getHotLaunchOptions(): BytedanceMiniprogram.LaunchParams { warn("字节跳动小游戏未提供热启动参数获取方式,请在 onShow 中获取"); return null; } diff --git a/src/net/http/IHttpEvent.ts b/src/net/http/IHttpEvent.ts index 7127946..af7948a 100644 --- a/src/net/http/IHttpEvent.ts +++ b/src/net/http/IHttpEvent.ts @@ -8,7 +8,7 @@ import { IHttpResponse } from "./IHttpResponse"; export interface IHttpEvent { /** 名称 */ - name: string; + name?: string; /** 自定义参数 */ data?: any; /** 网络请求成功 */ diff --git a/src/net/nettools/ReadNetFile.ts b/src/net/nettools/ReadNetFile.ts new file mode 100644 index 0000000..9b436b1 --- /dev/null +++ b/src/net/nettools/ReadNetFile.ts @@ -0,0 +1,29 @@ +/** + * @Author: Gongxh + * @Date: 2025-04-18 + * @Description: 读取网络文件内容 + */ + +import { Time } from "../../tool/Time"; +import { HttpManager } from "../http/HttpManager"; +import { IHttpResponse } from "../http/IHttpResponse"; + +export class ReadNetFile { + constructor(res: { url: string, timeout: number, responseType: "text" | "json" | "arraybuffer", onComplete: (data: any) => void, onError: (code: number, message: string) => void }) { + // 地址上带时间戳参数 确保每次请求都到服务器上请求最新配置,而不是拿到上次请求的缓存数据 + let url = res.url; + if (url.indexOf("?") > -1) { + url += `&timeStamp=${Time.now()}`; + } else { + url += `?timeStamp=${Time.now()}`; + } + HttpManager.get(url, null, res.responseType, { + onComplete: (response: IHttpResponse) => { + res.onComplete(response.data); + }, + onError: (response: IHttpResponse) => { + res.onError(response.statusCode, response.message); + } + }, null, res.timeout || 6); + } +} \ No newline at end of file diff --git a/src/tool/Utils.ts b/src/tool/Utils.ts index a037231..47a5386 100644 --- a/src/tool/Utils.ts +++ b/src/tool/Utils.ts @@ -36,4 +36,15 @@ export class Utils { return 0; } + /** + * 判断传入的字符串是否是json格式的字符串 + */ + public static isJsonString(str: string): boolean { + try { + JSON.parse(str); + return true; + } catch (e) { + return false; + } + } } \ No newline at end of file