当前位置:首页>鸿蒙APP>用鸿蒙 ArkTS 封装网络层,我折腾了整整一个下午

用鸿蒙 ArkTS 封装网络层,我折腾了整整一个下午

  • 2026-10-31 08:21:47
用鸿蒙 ArkTS 封装网络层,我折腾了整整一个下午

用鸿蒙 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 协议,转载请注明出处。

最新文章

随机文章