用鸿蒙 ArkTS 封装网络层,我折腾了整整一个下午
上周五下午两点,我打算给项目写一个通用的 HTTP 请求封装。预估一小时搞定,结果搞到六点半,还吃了外卖继续改。这篇文章就是那个下午的流水账。
一开始我用的 http 模块
鸿蒙的 @ohos.net.http 是最基础的网络 API,用法像这样:
import http from '@ohos.net.http';const httpRequest = http.createHttp();httpRequest.request( 'https://api.example.com/user', { method: http.RequestMethod.GET, header: { 'Content-Type': 'application/json' }, readTimeout: 6000, connectTimeout: 6000 }, (err, data) => { if (err) { console.error('请求失败', err.message); return; } console.log(data.result); httpRequest.destroy(); // 用完记得销毁! });
用着没啥问题,但我需要统一处理 Token、统一处理 loading 状态、统一处理错误码。于是我开始写一个 HttpClient 类。
大概两点半,基础结构搭好了,能跑通,感觉还行。
然后问题来了
我想给每个请求自动带上 Authorization: Bearer <token>,逻辑很简单,从 AppStorage 里取。写出来大概是这样:
const token = AppStorage.get<string>('userToken') ?? '';const headers: Record<string, string> = { 'Content-Type': 'application/json', 'Authorization': `Bearer {token}`, 'Content-Type': 'application/json' }); const response = await session.fetch(request); return response.toJSON();}
rcp 默认支持 Promise,不用再套 callback,代码干净很多。
然后我花了四十分钟把之前写的 callback 风格全改成 async/await。改完,爽了大概十分钟。
后来发现 toJSON() 不是万能的
晚上五点,测试后端返回的某个接口,toJSON() 直接抛异常了。原因是那个接口返回的 Content-Type 是 text/html(后端的锅,但我们改不了那个服务)。
toJSON() 只有在响应体是合法 JSON 的时候才能用,这一点文档里写了,但我没仔细看。
改成手动处理:
const response = await session.fetch(request);let result: unknown;const contentType = response.headers?.['content-type'] ?? '';if (contentType.includes('application/json')) { result = response.toJSON();} else { const raw = await response.toString(); // 尝试 parse,失败就直接用原始字符串 try { result = JSON.parse(raw); } catch { result = raw; }}
这段逻辑写完,五点半了。外卖也到了。
吃完饭,还有一个坑
我以为完了,其实没完。
项目里有个接口需要上传文件(头像),我按照 rcp 文档写了 multipart 上传,编译通过,真机跑直接报权限异常。
排查了一圈,发现 module.json5 里漏了 ohos.permission.INTERNET——不,等等,这个我肯定加了。
真正的原因是:文件读取权限。我从相册选出来的图片路径,直接往 rcp 里传,鸿蒙不让你这么干,你得先用 fs.copyFileSync 把文件复制到应用沙箱目录,再从沙箱读,才能上传。
import fs from '@ohos.file.fs';// 先把相册路径的文件复制到沙箱const sandboxPath = getContext().cacheDir + '/upload_tmp.jpg';fs.copyFileSync(selectedPhotoUri, sandboxPath);// 再用沙箱路径上传const fileContent = fs.readFileSync(sandboxPath);// ... multipart 构建
这个坑我觉得文档里完全没说清楚。或者说有说,藏在文件管理那一章,不在网络请求章节里,谁搜网络请求的时候会去看文件管理?
说几句心里话
我个人对 rcp 的整体印象是正向的——Promise API、更好的超时控制、更清晰的 Session 概念,用起来比老的 http 模块舒服。但坑还是有,主要集中在边界情况上:非 JSON 响应、文件上传权限、证书配置。
如果你现在开新项目,我建议直接用 rcp,别碰 http 模块了。但别指望文档能告诉你所有的坑,它只告诉你 happy path。
你有没有在鸿蒙网络这里被坑过?留言聊聊。
本文遵循 MIT 协议,转载请注明出处。