鸿蒙 韶非 UI 系列:HTTP 数据请求 @ohos.net.http,告别前端 fetch,鸿蒙网络栈入门第一篇 鸿蒙 韶非 UI 系列HTTP 数据请求 ohos.net.http告别前端 fetch鸿蒙网络栈入门第一篇写在前面如果你写过 ArkUI 之外的任何鸿蒙应用能力大概率第一个想做的就是「调接口」后端给你一个 RESTful 接口https://api.example.com/users前端 React 用fetch(url)一行搞定。鸿蒙 ArkTS 里你写fetch——编译报错「找不到 fetch」。你查文档发现鸿蒙不是浏览器运行环境没有fetch/XHR/axios要调接口得用专门的网络栈ohos.net.http。你点进去发现http.createHttp()HttpRequest.request()HttpRequestOptions一堆配置项 HttpResponse字段一堆 异步两种姿势 错误码和状态码要分清——比fetch复杂十倍一脸懵。这是「前端思维」和「鸿蒙原生网络栈」的分水岭。鸿蒙给的网络栈答案是ohos.net.http——createHttp()创建请求器、request()发 GET/POST、HttpRequestOptions配头/超时/协议/数据类型、HttpResponse拿响应码头体。本文就用一个真机可跑的「调 httpbin.org 公开测试接口」demo把ohos.net.http从「听名字一脸懵」讲到「下个项目直接抄」。代码托管在 AtomGit文末有链接真机实拍截图作证。这是非 UI 系列第一篇ArkUI 十篇凑齐后转网络栈入门。适合人群写过 ArkUI、第一次调鸿蒙网络接口的同学。不适合人群还在学State的同学——出门左转看我的入门篇。一、先讲清楚ohos.net.http到底是啥一句话ohos.net.http是鸿蒙原生 HTTP 网络栈管「发请求、收响应、控超时、销毁」全流程。你之前写前端用fetch/axios是浏览器宿主 API——鸿蒙不是浏览器环境没有这些。ohos.net.http是鸿蒙专门给应用调网络接口的原生模块能力对标fetch但更精细可控。核心 API 一览API作用一句话理解http.createHttp()创建请求器「造一个 HttpRequest 实例,后面用它发请求」httpReq.request(url, options)发请求「GET/POST/PUT/DELETE 都通过它」HttpRequestOptions配置项「method/header/超时/协议/数据类型」HttpResponse响应「responseCode header result」httpReq.destroy()销毁请求器「不用了销毁,防内存漏」记住这五个往下看。二、动手一个调 httpbin.org 的 GET/POST demo2.1 import 创建请求器importhttpfromohos.net.httpEntryComponentstruct Index{privatehttpReq:http.HttpRequesthttp.createHttp()StatestatusText:string尚未请求StaterespBody:stringStateisLoading:booleanfalse// ...}三个细节import http from ohos.net.http——http是 namespace,所有 API 都挂在它下面http.createHttp()/http.RequestMethod.GET/http.HttpDataType.STRING等http.HttpRequest是 interface不是 class,实例由http.createHttp()造,不能new http.HttpRequest()请求器是有状态资源,不用了要destroy()——比fetch多一步销毁管理2.2 GET 请求Promise 异步姿势asyncdoGet():Promisevoid{this.isLoadingtruethis.statusTextGET 请求中...try{constresp:http.HttpResponseawaitthis.httpReq.request(https://httpbin.org/get,{method:http.RequestMethod.GET,header:{X-Custom-Header:鸿蒙ArkTS-HTTP},connectTimeout:8000,readTimeout:8000,usingProtocol:http.HttpProtocol.HTTP1_1,expectDataType:http.HttpDataType.STRING,})this.statusTextGET 完成状态码${resp.responseCode}this.respBodyURL: https://httpbin.org/get\n\n${JSON.stringify(JSON.parse(resp.resultasstring),null,2)}}catch(e){this.statusTextGET 失败${e.message}this.respBody}finally{this.isLoadingfalse}}httpReq.request(url, options)返回PromiseHttpResponse,用await等响应。HttpRequestOptions常用字段字段作用默认methodRequestMethod 枚举GETheader请求头对象{}extraData请求体POST 用-connectTimeout连接超时ms60000readTimeout读取超时ms60000usingProtocolHTTP 协议HTTP1_1expectDataType期望响应数据类型STRING2.3 POST 请求传 JSON 体asyncdoPost():Promisevoid{this.isLoadingtruethis.statusTextPOST 请求中...try{constbody:Recordstring,string{user:鸿蒙开发者,action:login,ts:${Date.now()}}constresp:http.HttpResponseawaitthis.httpReq.request(https://httpbin.org/post,{method:http.RequestMethod.POST,header:{Content-Type:application/json,X-Request-From:ArkTS},extraData:JSON.stringify(body),connectTimeout:8000,readTimeout:8000,usingProtocol:http.HttpProtocol.HTTP1_1,expectDataType:http.HttpDataType.STRING,})this.statusTextPOST 完成状态码${resp.responseCode}this.respBodyPOST 体 →\n${JSON.stringify(body,null,2)}\n\n响应 →\n${JSON.stringify(JSON.parse(resp.resultasstring),null,2)}}catch(e){this.statusTextPOST 失败${e.message}this.respBody}finally{this.isLoadingfalse}}POST 比 GET 多两步header加Content-Type: application/json——告诉服务端体是 JSONextraData: JSON.stringify(body)——把对象序列化成 JSON 字符串传ArkTS 强约束body不能是裸对象字面量arkts-no-untyped-obj-literals要先声明Recordstring, string再赋值。2.4 响应处理HttpResponse三字段resp.responseCode// 服务端状态码200/404/500resp.header// 响应头对象resp.result// 响应体string/Object/ArrayBuffer,取决于 expectDataTyperesp.resultType// 实际响应类型枚举新手最容易混淆的是result它的类型由expectDataType决定STRING→ string,ARRAY_BUFFER→ 二进制,默认Object→ 已 deprecated。我设了STRING,所以resp.result as string断言成字符串用。2.5 销毁请求器生命周期收尾aboutToDisappear():void{// 销毁 HttpRequest 释放资源不收易内存漏this.httpReq.destroy()}http.createHttp()造的请求器是有状态资源——底层持有 socket、缓冲区、连接池。组件销毁时不调destroy(),这些资源不会自动释放,长时间运行易内存漏。这是fetch没有的鸿蒙专属坑。2.6 UI 反馈区build(){Column({space:14}){Text(HTTP 数据请求 Demoohos.net.http).fontSize(22).fontWeight(FontWeight.Bold).margin({top:16})// 状态区isLoading 显示加载中,完成后显示状态码Column({space:8}){Text(状态).fontSize(14).fontColor(#007DFF)Text(this.statusText).fontSize(16).fontWeight(FontWeight.Bold).fontColor(#222).padding(10).backgroundColor(#F0F0F0).borderRadius(6).width(100%)}.width(100%).padding(14).backgroundColor(#fff).borderRadius(10)// 按钮区GET / POST / 清空Row({space:10}){Button(GET 请求).backgroundColor(#007DFF).fontColor(#fff).height(40).layoutWeight(1).enabled(!this.isLoading).onClick((){this.doGet()})Button(POST 请求).backgroundColor(#FF4D4F).fontColor(#fff).height(40).layoutWeight(1).enabled(!this.isLoading).onClick((){this.doPost()})Button(清空).backgroundColor(#eee).fontColor(#333).height(40).onClick((){this.statusText尚未请求;this.respBody})}.width(100%)// 响应体显示区滚得动长 JSON 体可滚Column({space:8}){Text(响应体).fontSize(14).fontColor(#007DFF)Scroll(){Text(this.respBody||点按钮发请求后,这里显示响应体).fontSize(12).fontColor(#555).fontFamily(sans-serif).padding(10).backgroundColor(#FAFAFA).borderRadius(6)}.height(58%).width(100%).scrollBar(BarState.Auto)}.width(100%).padding(14).backgroundColor(#fff).borderRadius(10).layoutWeight(1)}.padding(16).backgroundColor(#F5F6F8).height(100%).width(100%)}三、真机实拍调 httpbin.org 真发出去并真有响应我把这个 demo 装到真机上跑鸿蒙 6.1.1.125, API 24调 httpbin.org 公开测试接口下面两张都是真机实拍没有任何 P 图。初始态状态「尚未请求」 GET/POST/清空三按钮 响应体区提示点 GET 按钮发请求后的响应态状态「GET 完成状态码 200」 响应体区显示 httpbin.org 返回的 JSON重点看第二张状态显示「GET 完成状态码 200」——真发出去并真有响应。响应体区显示 httpbin.org 返回的 JSON里面能看到我设的X-Custom-Header: 鸿蒙ArkTS-HTTP被服务端 echo 回来——这就是header字段生效的证明。POST 同理体被 echo 回来证明extraData生效。四、ohos.net.httpvs 前端fetch啥差异新手最容易纠结的问题既然前端fetch那么简洁鸿蒙为啥要造一套独立的维度前端fetchohos.net.http运行环境浏览器宿主鸿蒙原生运行环境创建全局fetch()调即用http.createHttp()造实例销毁浏览器自管必须destroy()防漏超时配置AbortController signalconnectTimeout/readTimeout字段请求头headers字段header字段单数响应类型response.text()/json()/arrayBuffer()链式expectDataType预设 resp.result直取错误姿势Promisetry/catch同Promisetry/catch一句话决策鸿蒙应用调接口必须用ohos.net.http,不能用fetch不存在。鸿蒙不是浏览器,这套原生栈更精细可控,代价是销毁管理多一步。五、常见坑都是血泪坑症状解法用fetch/axios编译报错「找不到 fetch」鸿蒙用ohos.net.http,没有浏览器宿主 APIHttpRequest用new编译报错HttpRequest是 interface,用http.createHttp()造实例HttpDataType.STRING_TYPE编译报错「Property 不存在」真常量名是STRING不带_TYPE后缀不调destroy()长跑内存漏组件销毁aboutToDisappear调httpReq.destroy()裸对象字面量传extraData编译报错arkts-no-untyped-obj-literals先声明Recordstring, X变量再JSON.stringifyresp.result类型不明运行时报错设expectDataType: STRINGas string断言忘 INTERNET 权限请求发不出去module.json5 配ohos.permission.INTERNET,装机首次授权错误码和状态码混业务判断错e.message是错误码网络层,resp.responseCode是状态码应用层六、INTERNET 权限鸿蒙应用调网的硬门槛鸿蒙应用调网络接口,必须先在module.json5声明ohos.permission.INTERNET权限,否则请求发不出去编译会 WARN 提示。{module:{abilities:[{name:EntryAbility,srcEntry:./ets/entryability/EntryAbility.ets,requestPermissions:[{name:ohos.permission.INTERNET}]}]}}装机首次跑时,鸿蒙会弹权限询问框,用户同意后才能调网。这是鸿蒙安全模型的硬门槛——比浏览器fetch多一层权限管理。七、完整代码仓库本文所有代码都已托管到AtomGit,欢迎 clone、提 issue、点 star仓库地址https://atomgit.com/JaneConan/arkui-http-request仓库包含完整的「调 httpbin.org GET/POST」demo 工程Index.ets主页面http.createHttprequest UI 反馈 销毁doGet/doPost两个异步姿势示范HttpRequestOptions常用字段配置 HttpResponse三字段处理可直接用 DevEco Studio 打开运行需真机有网 INTERNET 权限授权八、下一步该学什么跑通这个 demo 之后,你的鸿蒙网络栈就入门了。这是非 UI 系列第一篇,后续按这个顺序往下文件 IOohos.file.fs下一篇沙箱读写 元信息查,告别裸 PersistentStorage 存大对象能力调用ohos.ability调起相机/相册/定位等系统能力,应用集成系统服务后台任务ohos.backgroundTask长时后台跑、保活、调度,真机部署必学数据持久化ohos.data.relationalStore鸿蒙 SQLite 封装,结构化数据存取WebSocketohos.net.webSocket长连接、推送、实时通讯,聊天应用必学写在最后ohos.net.http的本质,是**「鸿蒙原生网络栈」**——不是浏览器宿主 API,是鸿蒙专门给应用调接口的原生模块,能力对标fetch但更精细可控。代价是销毁管理多一步、权限管理多一层。一旦你开始用鸿蒙原生思维写网络调,你会发现大部分「调接口收响应」的需求,都是createHttprequestdestroy三步的自然结果。代码量比fetch多三行,可控性高九成。代码已经给你了,仓库链接在上面。现在关掉这篇文章,打开 DevEco Studio,把 demo 跑起来,亲手点 GET 感受下真发请求真收响应。跑通了,回来评论区打个「1」,我看看有多少人真的动手了。作者JaneConan仓库https://atomgit.com/JaneConan/arkui-http-request协议Apache-2.0,随便用,别告我