HarmonyOS 6.1 网络请求实战:从 createHttp 到数据驱动的完整链路

发布时间:2026/7/8 7:23:44
HarmonyOS 6.1 网络请求实战:从 createHttp 到数据驱动的完整链路 基于 NetworkDemo 实战验证覆盖 HTTP 请求全流程、错误处理、请求日志附带完整可运行代码写在前面做网络请求这事儿在 HarmonyOS 上比在 Android 上蛋疼不少。Android 有 Retrofit、OkHttp 一堆成熟的库HarmonyOS 就一个kit.NetworkKit的 http 模块用法偏底层没有自动 JSON 解析没有拦截器连请求日志都得自己打。但好消息是底层意味着可控。你知道每一步在干什么出了问题能直接定位。这篇文章就把我用http.createHttp()做网络请求踩过的坑全列出来。一、HTTP 请求五步流程先说清楚完整流程后面再逐个展开import{http}fromkit.NetworkKit// 1. 创建请求对象consthttpRequesthttp.createHttp()// 2. 发起请求httpRequest.request(url,{method:http.RequestMethod.GET,header:{Content-Type:application/json},connectTimeout:10000,readTimeout:10000}).then((response:http.HttpResponse){// 3. 处理成功响应constresult:stringresponse.resultasstringconstdataJSON.parse(result)// ...}).catch((err:Error){// 4. 处理失败console.error(err.message)}).finally((){// 5. 释放资源必须httpRequest.destroy()})看起来不复杂对吧但每一步都有坑。二、踩坑一不 destroy() 就内存泄漏http.createHttp()创建的请求对象是有限资源。如果你不发destroy()这个对象就一直占着内存和连接。连续发几十个请求不 destroy内存直接飙上去。必须在请求结束后调用 destroy()不管是 then 还是 catchhttpRequest.request(url,options).then((response){// 处理响应httpRequest.destroy()// then 里也要 destroy}).catch((err){// 处理错误httpRequest.destroy()// catch 里也要 destroy})更安全的写法是用 finally但 ArkTS 的 Promise 没有 finally……那就 then 和 catch 里都写一遍。麻烦但必须。三、踩坑二缺少 INTERNET 权限 静默失败这个坑坑了我一整个下午。请求发出去then 不进catch 也不进就好像从来没发过请求一样。最后发现是module.json5里忘了声明ohos.permission.INTERNET。关键点缺少权限不会报错不会抛异常就是静默失败。连 hilog 都看不到错误信息。// module.json5 { module: { requestPermissions: [ { name: ohos.permission.INTERNET } ] } }如果你发现网络请求发了没反应第一件事检查权限声明。四、踩坑三response.result 默认是 stringAndroid 的 Retrofit 能自动把 JSON 反序列化成对象HarmonyOS 的 http 模块不行。response.result默认返回 string你得自己JSON.parse.then((response:http.HttpResponse){if(response.responseCode200){constresult:stringresponse.resultasstringconstparsed:ObjectJSON.parse(result)this.postsparsedasPostItem[]}})注意as string这个类型转换。ArkTS strict 模式下不允许随意用as但response.result的类型是string | Object转成 string 是合理的。不过如果服务器返回的不是 JSON 字符串这里会崩。更安全的做法是先判断类型。五、踩坑四并发请求需要多个 http 对象一个httpRequest对象同时只能发一个请求。如果你需要并发比如同时请求列表和详情必须创建多个对象// 错误同一个对象发两个请求第二个会覆盖第一个consthttpRequesthttp.createHttp()httpRequest.request(url1,options1).then(...)httpRequest.request(url2,options2).then(...)// 正确每个请求创建独立对象constreq1http.createHttp()req1.request(url1,options1).then((){req1.destroy()})constreq2http.createHttp()req2.request(url2,options2).then((){req2.destroy()})六、请求配置项详解httpRequest.request(url,{method:http.RequestMethod.GET,// GET/POST/PUT/DELETEheader:{// 请求头Content-Type:application/json,Authorization:Bearer token},extraData:{// POST 请求体string 或 Objectname:test,value:123},connectTimeout:10000,// 连接超时 10秒readTimeout:10000// 读取超时 10秒})extraData 的坑GET 请求不能传 extraData传了会被忽略。POST 请求的 extraData 如果是 Object会自动 JSON.stringify。如果是 string就原样发送。这个行为文档写得不清楚实测出来的。七、请求日志模式线上排查问题请求日志是命根子。Demo 里实现了完整的日志记录privaterequestLogs:RequestLog[][]privateaddLog(url:string,method:string,status:number,duration:number):void{constnow:DatenewDate()consttime:stringnow.getHours().toString().padStart(2,0):now.getMinutes().toString().padStart(2,0):now.getSeconds().toString().padStart(2,0)constlog:RequestLog{url:url,method:method,status:status,duration:duration,time:time}this.requestLogs[log].concat(this.requestLogs)}每次请求记录 URL、方法、状态码、耗时。这个模式建议所有项目都做哪怕只是开发阶段用。耗时计算conststartTime:numberDate.now()httpRequest.request(url,options).then((response){constduration:numberDate.now()-startTimethis.addLog(url,GET,response.responseCode,duration)})注意Date.now()要在request()调用之前获取不是在 then 回调里。then 回调是异步的那时已经开始计算耗时了。八、数据驱动从网络数据到 UI网络请求的最终目的是驱动 UI 更新。基本模式声明 State 数据数组请求成功后赋值ForEach 渲染列表Stateposts:PostItem[][]// 请求成功后this.postsparsedasPostItem[]// UI 渲染ForEach(this.posts,(post:PostItem){Row(){Column(){Text(post.id.toString(). post.title.substring(0,30)).fontSize(12).fontColor(#333333)Text(post.body.substring(0,50)).fontSize(11).fontColor(#888888)}}.onClick((){this.fetchSinglePost(post.id)})},(post:PostItem)post.id.toString())注意 ForEach 的 key用post.id.toString()作为唯一标识不要省略。省略 key 会导致列表更新时全部重渲染性能问题严重。九、错误处理最佳实践网络请求的错误分两类HTTP 错误服务器返回 4xx/5xx在 then 里通过response.responseCode判断网络错误超时、断网、DNS 解析失败在 catch 里处理.then((response:http.HttpResponse){if(response.responseCode200){// 成功}elseif(response.responseCode401){// token 过期跳转登录}else{// 其他 HTTP 错误this.errorMsgHTTP response.responseCode.toString()}}).catch((err:Error){// 网络层错误if(err.message.indexOf(timeout)0){this.errorMsg请求超时请检查网络}else{this.errorMsg网络错误: err.message}})十、网络请求不会阻塞 UI一个常见疑问主线程发网络请求会不会卡 UI不会。httpRequest.request()是异步的底层用 native 线程执行网络 IO不会阻塞 JS 主线程。所以短请求不需要放 TaskPool。但如果请求后要做大量 JSON 解析比如 5000 条记录的列表解析本身可能卡 UI。这种情况应该用 TaskPool 做解析参考第 09 篇 TaskPool 的内容。写在最后HarmonyOS 的网络模块虽然不如 Retrofit 好用但胜在透明。每一行代码你都知道在干什么出了问题能直接定位。不像 Retrofit 好多魔法的背后行为出错的时候一脸懵。建议所有网络请求都封装一层至少把 destroy()、错误处理、日志记录统一起来。裸写http.createHttp()在大项目里维护成本太高。