鸿蒙端云一体的网络层设计:统一 HttpUtil、超时重试与错误码收敛
【摘要】 把鸿蒙端云一体的网络层收口到一个 HttpUtil:分层超时、只对可重试错误做指数退避重试、用统一 ApiResult 收敛错误码,附代码与实战细节。
鸿蒙端云一体的网络层设计:统一 HttpUtil、超时重试与错误码收敛
做端云一体的鸿蒙应用,最容易失控的不是 UI,也不是云函数,而是网络层。一开始每个页面自己写一份 http 请求,写着写着就会发现:超时时间不统一、错误处理五花八门、加个重试要改十几处。这篇把网络层的设计收敛成一条清晰的线:统一入口、统一超时与重试、统一错误码。
一、为什么必须收口到一个 HttpUtil
如果每个页面各自 @ohos.net.http,会出三个问题:
- 无法统一加超时、重试、日志;
- 错误码散落各处,排查要翻十个文件;
- 换后端地址或加签名字段时,改到崩溃。
所以第一件事:全应用只允许一个 HttpUtil 出口,其他模块一律调它。
二、超时:分两层
网络超时不是一个数能盖住的,至少要分两层:
- 连接超时(connectTimeout):建立 TCP 连接的时间,设短一点,5 秒;
- 读取超时(readTimeout):等响应体的时间,设长一点,15 秒。
const httpRequest = http.createHttp();
const res = await httpRequest.request(url, {
method: http.RequestMethod.POST,
header: { 'Content-Type': 'application/json' },
extraData: JSON.stringify(body),
connectTimeout: 5000,
readTimeout: 15000
});
三、重试:只重试“可重试”的错误
不是所有失败都该重试。盲目重试会把一个 400 变成十次 400,甚至触发风控。经验规则:
- 网络异常、连接超时、5xx:可重试,指数退避(1s、2s、4s),最多 3 次;
- 4xx(除 429):不重试,直接报错;
- 429 限流:退避后重试,且读取 Retry-After。
async function requestWithRetry(cfg, maxRetry = 3) {
let lastErr;
for (let i = 0; i <= maxRetry; i++) {
try {
const r = await doRequest(cfg);
if (r.status >= 500 && i < maxRetry) throw new Error('server 5xx');
return r;
} catch (e) {
lastErr = e;
if (!isRetryable(e) || i === maxRetry) break;
await sleep(1000 * Math.pow(2, i));
}
}
throw lastErr;
}
注意:只有幂等请求(GET、带幂等键的写操作)才能安全重试。写操作重试前先确认服务端有幂等保护,否则可能重复下单。
四、错误码收敛:给上层一个“业务错误”
底层可能是 HTTP 状态码、也可能是业务 code,还可能是网络异常。上层不应该关心这些差异,网络层应该把它们统一成一种结构:
type ApiResult<T> = { ok: true; data: T } | { ok: false; code: string; msg: string };
规则:
- 2xx 且业务 code 正常 → ok:true;
- 4xx/5xx 或业务 code 异常 → ok:false,code 用业务错误码(如 AUTH_EXPIRED、RATE_LIMITED),msg 用可展示文案;
- 网络异常 → ok:false,code=NETWORK_ERROR。
这样页面只写 if (!res.ok) 处理业务错误,不用再判断一堆 HTTP 状态码。
五、几个实战细节
- 统一加日志与 traceId:每次请求带一个 traceId,服务端回写,出问题一搜链路日志就能定位。
- 取消请求:页面退出时 abort 未完成的请求,避免回调打到一个已销毁的页面。
- 鉴权拦截:token 过期统一在 HttpUtil 里拦截 401,跳登录,不要让每个接口自己处理。
- 不要吞异常:catch 里至少 log,否则线上永远找不到问题。
小结
网络层设计的核心不是写多少代码,而是把变化收敛到一个地方:入口一个、超时重试一处、错误码一种。做到这三点,后面加接口、换后端、排查问题都会轻很多。端云一体的项目尤其如此——云侧会变,端侧网络层得稳。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)