鸿蒙原生 HTTP 请求实战:GET、POST、PUT、DELETE 与错误排查

写鸿蒙应用,页面搭好了,下一步就是接接口。可还没发出第一个请求,就容易先纠结一件事:网络库选哪个,要不要先封装一套?

发起常见的 HTTP 请求,可以直接使用鸿蒙的原生网络 API。

这篇《鸿蒙 API 避坑录》,我们调试 @kit.NetworkKit 中的 http:先发出请求,再用设备接口验证 GET、POST、PUT、DELETE,最后看状态码、业务结果和连接失败该怎么区分。

这次调试什么?

用来联调的是一组设备管理接口:新增设备、查询详情、修改信息、删除记录。重点看请求方法、地址和 JSON 是否按接口约定发出,以及响应能不能证明操作成功。

截图中的页面只负责填写参数、展示响应,方便对照每次请求。

img

本文配图均来自模拟器,本次使用 10.0.2.2:62633 访问电脑上的联调服务。这个地址对应本次环境,照着做时要换成自己环境里可达的服务地址;真机访问电脑上的服务,通常需要使用电脑的局域网 IP,并确认网络可达。

一次原生请求,核心就这几步

先在 entry/src/main/module.json5 的 module 下声明网络权限,下面是配置片段:

"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET"
  }
]

项目把请求代码集中放在 httpService.ets。下面提炼出 GET 的核心流程:import 放在文件顶部,其余调用放在异步函数内,url 是传入的完整接口地址:

import { http } from '@kit.NetworkKit';

// 每次请求创建独立的请求对象
const request = http.createHttp();
try {
  const response = await request.request(url, {
    method: http.RequestMethod.GET,
    expectDataType: http.HttpDataType.STRING,
    connectTimeout: 10000,
    readTimeout: 10000,
    usingCache: false
  });

  const statusCode: number = response.responseCode;
  const responseBody = response.result;
} finally {
  request.destroy();
}

顺着读下来,就是创建对象、发请求、取响应,最后释放资源。这里省略了异常展示,完整项目会在 catch 中保留错误码和错误信息。

responseCode 是 HTTP 状态码,result 是响应内容。为了直接检查响应原文,这里指定按字符串接收;联调时希望访问服务端,因此关闭此次请求的缓存使用。

代码还设置了两个超时参数,数值单位都是毫秒。本文没有做超时边界测试,不把截图里的单次耗时当作性能结论。

destroy() 放在 finally 中,保证请求正常返回或抛出异常后,都会执行释放。下一次发送,再创建新的请求对象。

POST 传 JSON,别只改请求方法

GET 查询设备时,接口地址里带上记录 ID;POST 新增设备时,还要把设备信息放进请求体。

截图里发送的是这段演示数据:

{
  "deviceName": "米饭测试0001机",
  "deviceModel": "Demo",
  "osVersion": "演示版本"
}

img

对应到请求参数,关键是下面三个字段。这是 request() 第二个参数中的配置片段,body 为输入框里的字符串:

method: http.RequestMethod.POST,
header: {
  'Content-Type': 'application/json'
},
extraData: body

Content-Type 说明内容采用什么格式,extraData 才装着实际发送的数据。可以把前者理解成包裹上的标签,后者才是包裹里的东西。

标签写着 JSON,不代表里面的文字自动就成了合法 JSON。

本次示例直接发送输入的字符串,没有在发送前校验 JSON。少一个双引号、多一个逗号,或者字段类型不符合接口要求,都需要检查请求内容,不能一看到失败就怀疑网络。

img

这次新增接口返回的 data 是 4,后续查询、修改和删除,就围绕这条记录继续。

把四种方法串起来,才像一次联调

对照这个项目的后端,操作顺序可以写成下面这样:

新增:POST   /api/device
查询:GET    /api/device/4
修改:PUT    /api/device/4
删除:DELETE /api/device/4

这里的 4 来自上一次新增的响应,不能每次照抄。PUT 要提交修改后的内容,当前后端要求 deviceName 不能为空;DELETE 从路径读取 ID,不需要填写请求体,后端执行的是逻辑删除。

img

这张图能确认四次请求及其 HTTP 状态码。要进一步确认修改是否生效,可以在 PUT 后再发一次 GET,核对返回的设备名称;本组截图没有展示这一步,不把它算进已完成的验证。

本篇调试的是四种常用方法,并不代表系统只支持这四种。换成其他业务接口,请求方法、路径和字段仍要按对应接口约定填写。

页面显示成功,还得再看一眼响应体

这次调试中,页面按 HTTP 状态码是否处于 2xx 范围显示请求成功或失败。

但接口业务有没有办成,还得看后端的约定。当前设备接口会返回 code 和 message,前面新增成功的截图里,业务 code 是 0。

HTTP 状态码和业务结果,要分开看。

遇到失败,也别只给页面留一句“网络异常”。这次请求返回的实际错误是:

2300007 Failed to connect to the server

img

它说明这次没能连接到服务器。具体是地址、端口、服务状态,还是网络可达性的问题,需要继续查;仅凭这张图,不能认定就是某一种原因。

排查时可以先核对地址和端口,再检查服务是否监听、设备能否访问。尤其别把电脑上的 localhost 原样填到另一台设备里,它指向的是发起请求的设备自身。

另外,截图只展示响应内容的前 300 字。联调时如果关键字段没显示出来,要继续检查完整响应,不能把页面截取当成接口只返回了这些内容。

重复发送请求也要看业务含义。查询通常便于反复核对,但 POST 新增可能再次创建记录,调试时要留意每次返回的 ID。

和 iOS、Android、Vue 里发请求有什么不同?

如果你从其他开发环境转过来,HTTP 方法、请求头、JSON 和状态码这些知识都能接着用。需要重新熟悉的,主要是平台提供的调用入口,以及权限、异步执行和错误处理方式。

开发环境不额外装库的请求入口调试时先关注什么
鸿蒙原生应用本文的 Network Kit http网络权限、请求参数、响应字段和对象释放
iOS 原生应用Foundation URLSession请求配置、返回的数据与响应信息
Android 原生应用HttpsURLConnection 等网络权限、线程与连接配置
Vue 网页浏览器原生 fetch请求体、响应解析、浏览器跨域限制

iOS 可以用系统提供的 URLSession 完成请求;Android 也有平台自带的 HTTP 客户端,并要求把网络操作放到主 UI 线程之外。它们都不需要为了发出一次请求就先装第三方库。参见 Apple URLSession 文档[1] 与 Android 网络连接指南[2]。

这里尤其想和做 Web 的朋友对齐一个概念:Vue 是界面框架,在浏览器里发请求,可以直接用 fetch,也可以选 Axios。

Web 开发并非必须引入 Axios;鸿蒙也并非因为能用原生 API,就永远不需要请求封装。

Axios 的价值在于提供统一的调用方式,以及请求配置、拦截器等能力,方便集中处理公共请求头和响应。要不要引入,取决于项目里的重复工作和维护成本。Axios 官方文档[3]

从 Vue/Web 切过来调鸿蒙接口,有两个习惯值得重新核对。

一个是响应字段。本文鸿蒙示例从 responseCode 和 result 读取状态码和内容;浏览器 fetch 返回的是 Response,需要检查 status 或 ok,再通过 json()、text() 等方法读取内容。fetch 收到 404、500 时也不会仅因这个状态码就进入 catch,所以不能把“没抛异常”当成接口成功。MDN:使用 Fetch[4]

另一个是跨域。Vue 网页里的请求受浏览器同源策略和 CORS 规则约束,换成 Axios 也绕不过去。本文调试的是鸿蒙原生网络 API,不应把网页里的跨域报错处理方法原样搬过来;如果请求发生在 WebView 内的网页里,则还要按 Web 环境分析。MDN:CORS[5]

所以换到鸿蒙,调接口的顺序仍然熟悉:确认地址能连上,核对方法和参数,再结合 HTTP 状态码与响应体判断结果。先把这条链路验证清楚,之后再考虑统一鉴权、错误处理和请求封装。

本篇实际素材覆盖模拟器中的四种请求方法、JSON 传参和连接失败反馈;上面的跨平台部分是文档对照,没有做同一接口的多端性能测试,也不据此判断哪个平台请求更快。

源码地址,复制到浏览器打开:

https://github.com/Luckyude/harmonyos-api-lab

鸿蒙工程在 apps/mf_api,配套联调服务在 backend。系统能力可对照华为的 HTTP 请求开发指南[6] 和 OpenHarmony 的 使用 HTTP 访问网络[7],具体版本以自己的工程 SDK 为准。

参考资料

以下为文中提及的官方文档:


更多鸿蒙 API 调试与实践,欢迎关注公众号「程序猿米饭」。

img

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐