【鸿蒙心迹】HarmonyOS笔记30:网络请求与JSON解析
🔥 个人主页: 杨利杰YJlio
❄️ 个人专栏: 《Windows 疑难杂症与工单复盘案例库》 《Sysinternals实战教程》
《WINDOWS教程》 《Windows PowerShell 实战》 《IOS插件分析测试》
🌟 让复杂的事情更简单,让重复的工作自动化


文章目录
大家好,我是杨利杰 YJlio。
上一节整理了Promise与async/await。这一节我把等待逻辑接到网络请求上:先配置权限和接口,再检查HTTP响应,解析JSON,最后把校验后的message交给页面。
本篇编号030,计划日期2026年10月20日。原稿已保留。本文代码尚未经过SDK编译或设备实测,图片均为概念示意;不把示例当成已完成的联网实验。
一、先分清模拟结果与真实请求
原稿用Promise.resolve返回一个带message的对象,适合练习页面赋值,但它没有发送HTTP请求,也没有解析服务端JSON文本。
本篇改用Network Kit的http接口。完整路径是:配置地址→创建请求→await响应→检查状态和响应体→解析字段→更新状态。任何一步失败,都应进入错误处理。
取得响应、解析成功与业务成功是不同的判断,不能只看到Promise完成就显示成功。
本例约定HTTP状态为200,响应为含string类型message字段的JSON对象。这是练习契约,不代表所有接口都采用同样结构;真实业务还可能有code、data等字段,需要另行校验。

二、配置网络权限和实际接口
在entry/src/main/module.json5的module对象下,合并requestPermissions。下面是局部片段,不要用它覆盖整个配置文件,也不要重复建立同名字段:
"requestPermissions": [
{ "name": "ohos.permission.INTERNET" }
]
保留原有权限项。本节不加入与请求无关的权限。
代码中的ENDPOINT默认留空,运行前改成自己的或有授权的HTTPS测试接口。接口应按本篇契约返回JSON对象。这里不填一个可能返回HTML的公共页面来冒充业务接口。
import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
const ENDPOINT: string = '';
interface MessagePayload {
message: string;
}
没有真实环境时,先核对代码和契约;连接、证书与服务端响应仍属于待验证事项。不要为让示例运行而关闭证书验证。

三、一次请求创建一个HttpRequest对象
下面函数和后面的parseMessage、页面组件放在同一个Index.ets学习文件中。创建请求后,用finally释放资源:
async function fetchMessage(url: string): Promise<string> {
if (!url.startsWith('https://')) {
throw new Error('请先配置授权的HTTPS接口地址');
}
const request = http.createHttp();
try {
const response = await request.request(url, {
method: http.RequestMethod.GET,
expectDataType: http.HttpDataType.STRING,
connectTimeout: 10000,
readTimeout: 10000
});
if (response.responseCode !== 200) {
throw new Error(`HTTP状态不符合预期:${response.responseCode}`);
}
if (typeof response.result !== 'string') {
throw new Error('响应体不是字符串');
}
return parseMessage(response.result);
} finally {
request.destroy();
}
}
connectTimeout和readTimeout是毫秒配置值,不是实测耗时,也不能相加写成严格的整体任务时限。地址前缀检查只是本例的提示,不是完整的URL合法性或可信性审查。
按官方接口说明,每次请求创建自己的HttpRequest对象,请求结束后调用destroy。这里没有复用已销毁的对象。

四、HTTP状态与响应体分别检查
本例先要求responseCode为200,再检查result确实是string。即使请求Promise返回了响应,也可能拿到不符合本例要求的HTTP状态。
expectDataType指定希望得到字符串,代码仍保留运行时类型检查。不要直接用as string把不匹配的响应强行当作JSON文本。
200也不能保证响应体是合法JSON,更不能代替业务字段校验。接口返回错误页、空文本或另一套JSON结构时,后续处理仍应失败。

五、JSON.parse之后继续验证message
function parseMessage(text: string): string {
const parsed = JSON.parse(text) as MessagePayload | null;
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
throw new Error('JSON顶层必须是对象');
}
if (typeof parsed.message !== 'string') {
throw new Error('JSON缺少string类型的message');
}
return parsed.message;
}
JSON.parse遇到非法文本会抛出异常。合法JSON也可能是null、数组、数字或字符串,因此还要检查顶层结构与message类型。
as只帮助编译期描述类型,不会替服务端数据做运行时校验。
这里允许message为空字符串,因为契约只要求string。如果业务要求非空,需要明确增加校验;不能把空字符串和网络异常混为一谈。

六、页面只显示校验后的文本
下面组件调用fetchMessage。新请求开始时先清空旧文本和旧错误,避免把上一轮结果当成本轮结果:
@Entry
@Component
struct Index {
@State loading: boolean = false;
@State message: string = '';
@State errorMessage: string = '';
@State completed: boolean = false;
private async loadData(): Promise<void> {
if (this.loading) return;
this.loading = true;
this.message = '';
this.errorMessage = '';
this.completed = false;
try {
this.message = await fetchMessage(ENDPOINT);
this.completed = true;
} catch (error) {
const err = error as BusinessError;
this.errorMessage = String(err.message);
console.error(`request failed: ${err.code}, ${err.message}`);
} finally {
this.loading = false;
}
}
build() {
Column({ space: 16 }) {
Text('请求与JSON解析练习')
Button('加载数据')
.enabled(!this.loading)
.onClick(() => {
this.loadData()
})
if (this.loading) {
Text('处理中')
}
if (this.completed) {
Text(this.message.length === 0 ? 'message为空字符串' : this.message)
}
if (this.errorMessage.length > 0) {
Text(this.errorMessage)
}
}
.width('100%')
.height('100%')
.padding(24)
}
}
completed区分尚未完成与已取得空字符串;它只表示本例请求和字段检查完成,不是通用的业务成功标志。
示例中平台错误可含BusinessError错误码,手动抛出的Error不一定有code。保留完整诊断,但不要向日志写入令牌、Cookie或整段敏感响应。真实服务返回的业务错误结构需单独定义。

七、请求资源与页面状态分两层清理
| 层次 | finally中的操作 | 目的 |
|---|---|---|
| fetchMessage | request.destroy() | 释放本次请求资源 |
| loadData | loading=false | 结束页面加载状态,恢复按钮 |
请求层只返回校验后的string或抛出错误,页面层负责提示与状态。两层都处理各自的收尾,不能只恢复按钮而忘记请求资源。
finally负责收尾,不会自动重试,也不会自动替页面设计离开后的取消策略。
loading只限制当前组件重复进入。本例没有自动重试、缓存或离开页面时中断请求的实现;接入实际工程时应按接口能力设计,不能把重新点击按钮当作可靠重试机制。

八、按失败位置记录实验结果
| 场景 | 应检查的边界 | 实际结果 |
|---|---|---|
| ENDPOINT未配置 | 明确提示配置HTTPS地址 | 待验证 |
| 权限未声明 | 核对权限配置与完整错误 | 待验证 |
| 断网或超时 | 显示错误并结束加载 | 待验证 |
| 非200响应 | 不继续当作本例成功结果 | 待验证 |
| 非JSON文本 | 解析失败进入错误提示 | 待验证 |
| null、数组或字段类型不符 | 拒绝不符合契约的结构 | 待验证 |
| 合法message字符串 | 展示校验后的文本 | 待验证 |
| 合法空字符串 | 显示明确的空字符串提示 | 待验证 |
| 快速重复点击 | 当前页面不重复发起 | 待验证 |
记录实际SDK/API、工具和设备版本、请求时的网络环境、HTTP状态及错误信息。没有真实响应与设备日志,不能宣称联网成功、性能改善或兼容某个版本。

写在最后
这节我把原稿里的模拟赋值改成了完整的请求学习路径:权限和地址准备、请求对象创建、响应检查、JSON结构校验、页面映射和资源清理。
后续学习网络请求加载态与错误态时,可以在这条路径上逐步完善体验。先让页面提示对应实际阶段,再考虑重试与缓存,比较容易定位问题。
参考资料
- 华为开发者文档:HTTP数据请求指南。
- 华为开发者文档:http接口参考。请求对象、配置和资源释放以实际SDK对应文档为准。
- 原稿《发起网络请求并解析JSON》,030/102,计划日期2026-10-20;原稿保留。
声明:本文为个人学习笔记,代码未进行SDK编译、模拟器或设备实测,未验证真实接口返回。配图为概念示意,实际运行记录需在独立练习环境补充。

更多推荐


所有评论(0)