HarmonyOS Base64Util 同步 vs 异步:六个方法该怎么选?
文章目录
- 前言
- 一、同步版本解析
- encodeSync
- encodeToStrSync
- decodeSync
- 二、异步版本解析
- encode
- encodeToStr
- decode
- 三、Demo 中的四种组合
- 四、选型矩阵
- 五、关于 util.Type 参数
- 六、常见踩坑
- 踩坑1:同步方法在大文件上卡 UI
- 踩坑2:解码失败没有 try-catch
- 踩坑3:混用编码类型
- 七、总结
前言
近期发现一款很有意思的HarmonyOS 三方库, 地址 @pura/harmony-utils(V1.4.0) , 作者是"桃花镇童长老", 我这里也是直接通过该作者公布的源码进行案例编写进行,写了到目前写了一部分demo ,感觉确实很有帮助,这里呢也是开始写一个系列的演示demo 供大家参考。如有帮助可以在OpenHarmony中进行下载安装进行使用哦
案例demo导航展示
↓↓↓↓↓↓接下来言归正传 ↓↓↓↓
Base64Util 有 6 个方法,其中同步 3 个、异步 3 个,一一对应:
encode ↔ encodeSync encodeToStr ↔ encodeToStrSync decode ↔ decodeSync很多人看到有异步就直接用异步,看到有同步就觉得"同步方便直接用同步"。
但这两种选法都不严谨。正确的做法是根据数据量大小和调用场景来选。
一、同步版本解析
encodeSync
staticencodeSync(array:Uint8Array):Uint8Array{constbase64=newutil.Base64Helper();constresult=base64.encodeSync(array);returnresult;}特点:
- 直接返回值,不需要
await - 在当前线程执行,会阻塞主线程
- 适合小数据量(几KB以内)
encodeToStrSync
staticencodeToStrSync(array:Uint8Array,options?:util.Type):string{constbase64=newutil.Base64Helper();constresult=base64.encodeToStringSync(array,options);returnresult;}最常用的同步方法:直接返回 Base64 字符串,不需要await,不需要转换,拿来即用。
decodeSync
staticdecodeSync(array:Uint8Array|string,options?:util.Type):Uint8Array{constbase64=newutil.Base64Helper();constresult=base64.decodeSync(array,options);returnresult;}接受Uint8Array或string(Base64 字符串),直接返回Uint8Array。
二、异步版本解析
encode
staticencode(array:Uint8Array):Promise<Uint8Array>{constbase64=newutil.Base64Helper();returnbase64.encode(array);}返回Promise<Uint8Array>,必须用await或.then()处理结果。
encodeToStr
staticencodeToStr(array:Uint8Array,options?:util.Type):Promise<string>{constbase64=newutil.Base64Helper();returnbase64.encodeToString(array,options);}最常用的异步方法:返回Promise<string>,适合大文件编码或在 async 函数中调用。
decode
staticdecode(array:Uint8Array|string,options?:util.Type):Promise<Uint8Array>{constbase64=newutil.Base64Helper();returnbase64.decode(array,options);}三、Demo 中的四种组合
Base64DemoPage.ets演示了所有四种编解码组合:
asyncrunEncode(){constraw=this.textToUint8Array(this.inputText);this.addLog('输入',`原文长度:${raw.length}字节`,'info');if(this.syncMode){// 同步模式if(this.toStrMode){// 组合一:同步编码 → 字符串constencoded=Base64Util.encodeToStrSync(raw);constdecodedRaw=Base64Util.decodeSync(encoded);constdecoded=this.uint8ArrayToText(decodedRaw);this.results=[{label:'encodeToStrSync',value:encoded,byteLen:raw.length},{label:'decodeSync→Str',value:decoded,byteLen:decoded.length},];this.addLog('Sync','encodeToStrSync + decodeSync 完成','success');}else{// 组合二:同步编码 → Uint8Arrayconstencoded=Base64Util.encodeSync(raw);constdecoded=Base64Util.decodeSync(encoded);this.results=[{label:'encodeSync (Uint8Array)',value:this.uint8ArrayToText(encoded),byteLen:raw.length},{label:'decodeSync (Uint8Array)',value:this.uint8ArrayToText(decoded),byteLen:decoded.length},];this.addLog('Sync','encodeSync + decodeSync 完成','success');}}else{// 异步模式if(this.toStrMode){// 组合三:异步编码 → 字符串constencoded=awaitBase64Util.encodeToStr(raw);constdecodedRaw=awaitBase64Util.decode(encoded);constdecoded=this.uint8ArrayToText(decodedRaw);this.results=[{label:'encodeToStr (Promise)',value:encoded,byteLen:raw.length},{label:'decode (Promise)→Str',value:decoded,byteLen:decoded.length},];this.addLog('Async','encodeToStr + decode 完成','success');}else{// 组合四:异步编码 → Uint8Arrayconstencoded=awaitBase64Util.encode(raw);constdecoded=awaitBase64Util.decode(encoded);this.results=[{label:'encode (Promise)',value:this.uint8ArrayToText(encoded),byteLen:raw.length},{label:'decode (Promise)',value:this.uint8ArrayToText(decoded),byteLen:decoded.length},];this.addLog('Async','encode + decode 完成','success');}}}解码演示(独立 Tab):
asyncrunDecode(){if(this.inputText.trim()===''){this.addLog('解码','请输入 Base64 字符串','warn');return;}try{letdecoded:Uint8Array;if(this.syncMode){decoded=Base64Util.decodeSync(this.inputText.trim());}else{decoded=awaitBase64Util.decode(this.inputText.trim());}consttext=this.uint8ArrayToText(decoded);this.results=[{label:'解码结果',value:text,byteLen:decoded.length},];this.addLog('解码',`解码成功${decoded.length}字节`,'success');}catch(e){this.addLog('解码',`解码失败:${(easError).message}`,'error');}}四、选型矩阵
| 场景 | 数据量 | 推荐方法 | 原因 |
|---|---|---|---|
| 编码小图标/小图片 | < 1KB | encodeToStrSync | 同步简洁,数据量小不卡 |
| 编码大图片/文件 | > 100KB | encodeToStr(async) | 大数据异步,不阻塞 UI |
| 解码服务器 Token | 几十字节 | decodeSync | 同步即可,超小数据 |
| 解码大文件 | > 100KB | decode(async) | 异步解码,避免卡顿 |
| 需要继续传给其他方法 | 任意 | 看下游是否异步链路 | 保持链路一致性 |
在aboutToAppear中初始化 | 任意 | Sync版本 | 生命周期不是 async |
五、关于 util.Type 参数
所有方法都有一个可选的options?: util.Type参数,用于指定 Base64 编码的变体:
| 值 | 说明 |
|---|---|
util.Type.BASIC | 标准 Base64(默认,使用+和/,末尾补=) |
util.Type.MIME | MIME 格式,每 76 字符加一个换行\r\n |
util.Type.URL_SAFE | URL 安全格式,用-替代+,_替代/ |
util.Type.BASIC_URL_SAFE | URL 安全但不补= |
大多数场景用默认值(不传 options)即可。如果编码结果要放进 URL 参数里,应该用util.Type.URL_SAFE,否则+和/在 URL 中有特殊含义会出问题。
六、常见踩坑
踩坑1:同步方法在大文件上卡 UI
// ❌ 大文件用同步会冻结界面constbigFile:Uint8Array=...// 5MB 图片constencoded=Base64Util.encodeToStrSync(bigFile);// 卡住 UI// ✅ 改用异步constencoded=awaitBase64Util.encodeToStr(bigFile);// 不阻塞踩坑2:解码失败没有 try-catch
// ❌ 没有处理解码失败constdecoded=Base64Util.decodeSync(invalidBase64String);// 可能抛出// ✅ 包一层 try-catchtry{constdecoded=Base64Util.decodeSync(invalidBase64String);}catch(e){console.error('解码失败:',(easError).message);}Base64 字符串如果不合法(含有非法字符、长度不对),decodeSync会抛异常。
踩坑3:混用编码类型
// ❌ 用 URL_SAFE 编码,却用默认选项解码constencoded=Base64Util.encodeToStrSync(data,util.Type.URL_SAFE);constdecoded=Base64Util.decodeSync(encoded);// 可能出错!// ✅ 编解码选项要一致constdecoded=Base64Util.decodeSync(encoded,util.Type.URL_SAFE);七、总结
选型口诀:
- 数据小(< 10KB)→ 用 Sync
- 数据大(> 100KB)→ 用 async/await
- 不确定 → 用 async,安全边际更大
- 要放 URL 里 → 加
util.Type.URL_SAFE - 解码一定要 try-catch
