news 2026/7/22 5:45:48

鸿蒙 韶非 UI 系列:HTTP 数据请求 @ohos.net.http,告别前端 fetch,鸿蒙网络栈入门第一篇

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙 韶非 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 demo

2.1 import + 创建请求器

importhttpfrom'@ohos.net.http'@Entry@Componentstruct Index{privatehttpReq:http.HttpRequest=http.createHttp()@StatestatusText:string='尚未请求'@StaterespBody:string=''@StateisLoading:boolean=false// ...}

三个细节:

  1. import http from '@ohos.net.http'——http是 namespace,所有 API 都挂在它下面(http.createHttp()/http.RequestMethod.GET/http.HttpDataType.STRING等)
  2. http.HttpRequest是 interface(不是 class),实例由http.createHttp()造,不能new http.HttpRequest()
  3. 请求器是有状态资源,不用了要destroy()——比fetch多一步销毁管理

2.2 GET 请求:Promise 异步姿势

asyncdoGet():Promise<void>{this.isLoading=truethis.statusText='GET 请求中...'try{constresp:http.HttpResponse=awaitthis.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.statusText=`GET 完成,状态码${resp.responseCode}`this.respBody=`URL: https://httpbin.org/get\n\n${JSON.stringify(JSON.parse(resp.resultasstring),null,2)}`}catch(e){this.statusText=`GET 失败:${e.message}`this.respBody=''}finally{this.isLoading=false}}

httpReq.request(url, options)返回Promise<HttpResponse>,用await等响应。HttpRequestOptions常用字段:

字段作用默认
methodRequestMethod 枚举GET
header请求头对象{}
extraData请求体(POST 用)-
connectTimeout连接超时(ms)60000
readTimeout读取超时(ms)60000
usingProtocolHTTP 协议HTTP1_1
expectDataType期望响应数据类型STRING

2.3 POST 请求:传 JSON 体

asyncdoPost():Promise<void>{this.isLoading=truethis.statusText='POST 请求中...'try{constbody:Record<string,string>={'user':'鸿蒙开发者','action':'login','ts':`${Date.now()}`}constresp:http.HttpResponse=awaitthis.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.statusText=`POST 完成,状态码${resp.responseCode}`this.respBody=`POST 体 →\n${JSON.stringify(body,null,2)}\n\n响应 →\n${JSON.stringify(JSON.parse(resp.resultasstring),null,2)}`}catch(e){this.statusText=`POST 失败:${e.message}`this.respBody=''}finally{this.isLoading=false}}

POST 比 GET 多两步:

  1. headerContent-Type: application/json——告诉服务端体是 JSON
  2. extraData: JSON.stringify(body)——把对象序列化成 JSON 字符串传

ArkTS 强约束:body不能是裸对象字面量(arkts-no-untyped-obj-literals),要先声明Record<string, string>再赋值。

2.4 响应处理:HttpResponse三字段

resp.responseCode// 服务端状态码(200/404/500)resp.header// 响应头对象resp.result// 响应体(string/Object/ArrayBuffer,取决于 expectDataType)resp.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 数据请求 Demo(@ohos.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那么简洁,鸿蒙为啥要造一套独立的?

维度前端fetch@ohos.net.http
运行环境浏览器宿主鸿蒙原生运行环境
创建全局fetch()调即用http.createHttp()造实例
销毁浏览器自管必须destroy()防漏
超时配置AbortController+ signalconnectTimeout/readTimeout字段
请求头headers字段header字段(单数)
响应类型response.text()/json()/arrayBuffer()链式expectDataType预设 +resp.result直取
错误姿势Promise+try/catchPromise+try/catch

一句话决策:鸿蒙应用调接口必须用@ohos.net.http,不能用fetch(不存在)。鸿蒙不是浏览器,这套原生栈更精细可控,代价是销毁管理多一步。


五、常见坑(都是血泪)

症状解法
fetch/axios编译报错「找不到 fetch」鸿蒙用@ohos.net.http,没有浏览器宿主 API
HttpRequestnew编译报错HttpRequest是 interface,用http.createHttp()造实例
HttpDataType.STRING_TYPE编译报错「Property 不存在」真常量名是STRING(不带_TYPE后缀)
不调destroy()长跑内存漏组件销毁aboutToDisappearhttpReq.destroy()
裸对象字面量传extraData编译报错arkts-no-untyped-obj-literals先声明Record<string, X>变量再JSON.stringify
resp.result类型不明运行时报错expectDataType: STRING+as 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.createHttp+request+ UI 反馈 + 销毁)
  • doGet/doPost两个异步姿势示范
  • HttpRequestOptions常用字段配置 +HttpResponse三字段处理
  • 可直接用 DevEco Studio 打开运行(需真机有网 + INTERNET 权限授权)

八、下一步该学什么?

跑通这个 demo 之后,你的鸿蒙网络栈就入门了。这是非 UI 系列第一篇,后续按这个顺序往下:

  1. 文件 IO@ohos.file.fs(下一篇):沙箱读写 + 元信息查,告别裸 PersistentStorage 存大对象
  2. 能力调用@ohos.ability:调起相机/相册/定位等系统能力,应用集成系统服务
  3. 后台任务@ohos.backgroundTask:长时后台跑、保活、调度,真机部署必学
  4. 数据持久化@ohos.data.relationalStore:鸿蒙 SQLite 封装,结构化数据存取
  5. WebSocket@ohos.net.webSocket:长连接、推送、实时通讯,聊天应用必学

写在最后

@ohos.net.http的本质,是**「鸿蒙原生网络栈」**——不是浏览器宿主 API,是鸿蒙专门给应用调接口的原生模块,能力对标fetch但更精细可控。代价是销毁管理多一步、权限管理多一层。

一旦你开始用鸿蒙原生思维写网络调,你会发现大部分「调接口收响应」的需求,都是createHttp+request+destroy三步的自然结果。代码量比fetch多三行,可控性高九成。

代码已经给你了,仓库链接在上面。现在关掉这篇文章,打开 DevEco Studio,把 demo 跑起来,亲手点 GET 感受下真发请求真收响应。

跑通了,回来评论区打个「1」,我看看有多少人真的动手了。🚀


作者:JaneConan
仓库:https://atomgit.com/JaneConan/arkui-http-request
协议:Apache-2.0,随便用,别告我

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/22 5:44:38

从自学到Deno核心贡献者的技术成长之路

1. 从辍学生到Deno核心贡献者的逆袭之路2019年&#xff0c;一个名为justjavac的中国开发者突然出现在Deno项目的贡献者名单前列。这个网名背后&#xff0c;是一位只有高中学历的普通程序员。从网吧自学编程到成为国际知名开源项目的核心贡献者&#xff0c;他用了整整十年时间完…

作者头像 李华
网站建设 2026/7/22 5:43:55

K3S节点添加失败问题分析与解决方案

1. K3S节点添加失败问题概述最近在部署K3S集群时遇到了节点添加失败的问题&#xff0c;错误提示为"Node password rejected, duplicate hostname or contents of /etc/rancher/node/password may not match server node-passwd entry"。这个问题在K3S集群部署中相当常…

作者头像 李华
网站建设 2026/7/22 5:40:49

Spring Boot多数据源配置实战:Druid+MyBatisPlus最佳实践

1. 多数据源架构的必要性与挑战在企业级应用开发中&#xff0c;多数据源的需求非常普遍。我最近在开发一个电商平台时&#xff0c;就遇到了需要同时访问商品数据库和用户数据库的场景。这种架构设计通常出现在以下典型场景中&#xff1a;业务数据隔离需求&#xff08;如多租户系…

作者头像 李华
网站建设 2026/7/22 5:39:57

FT891与SDR切换器一线通方案:硬件集成与抗干扰实战

那天晚上&#xff0c;我正调试着新到的 Yaesu FT-891 短波电台和手头的 SDR&#xff08;软件定义无线电&#xff09;设备&#xff0c;桌上摊着好几根线——电台要供电&#xff0c;SDR 要供电&#xff0c;PTT&#xff08;Push-to-Talk&#xff09;信号还要单独接。电源线、数据线…

作者头像 李华
网站建设 2026/7/22 5:39:33

6款高效免费软件推荐:办公设计全搞定

1. 前言&#xff1a;免费软件的实用价值在这个数字化时代&#xff0c;优质软件能极大提升我们的工作效率和生活品质。但很多专业软件价格昂贵&#xff0c;对普通用户来说负担不小。今天我要分享6款完全免费的实用软件&#xff0c;它们不仅功能强大&#xff0c;而且能解决日常工…

作者头像 李华