HarmonyOS ------ 发送网络请求(ArkTS)实战笔记(RemoteCommunicationKit rcp)
这篇是我啃官方文档《发送网络请求(ArkTS)》时整理的学习笔记,主要是帮自己理顺三件事:
- HarmonyOS 里 网络请求到底是怎么发的 ?(不是浏览器那个
fetch...) rcp.createSession()+session.get/post/put/...这一套到底怎么用?- 遇到要提交表单、多部分上传(Form / MultipartForm)的时候,ArkTS 这边怎么写才好维护?
下面就是我按自己的理解整理的一套"实战向"梳理,方便以后写博客 / 复习 / 踩坑查漏。
一句话先记住
一句话记:
在 HarmonyOS 里,要发 HTTP 请求,不是随手来个
fetch(url)就完事,而是:👉 通过 RemoteCommunicationKit 的
rcp模块 创建一个session,👉 然后用
session.fetch / get / post / put / head / delete来发各种请求,👉 复杂数据用
Form/MultipartForm填到Request.content里。
1. 能在哪些设备上用?约束先过一眼
官方给的能力覆盖范围是:
- 支持设备:Phone、2in1、Tablet、Wearable
- 从 5.1.1(19) 开始:新增支持 TV 设备
简单理解:
只要是主流 HarmonyOS 设备,基本都能用这套网络请求能力,电视也从 5.1.1 之后跟上了。
2. RemoteCommunicationKit 基础:rcp + Session
2.1 导入模块
所有网络请求的入口都在 @kit.RemoteCommunicationKit 的 rcp 命名空间里:
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
BusinessError 用来兜底各种错误码和异常信息。
2.2 Session:所有请求的"会话对象"
核心概念只有一个:先创建会话,再用会话发请求。
const session = rcp.createSession();
之后:
session.fetch(...)session.get(...)session.post(...)session.put(...)session.head(...)session.delete(...)
全都挂在这个 session 上。
我自己的习惯是:
- 一段逻辑里用完会话就
session.close()一下,- 防止长时间占用资源,特别是频繁发请求的时候。
3. 通用的 fetch:自己构造 Request
fetch 比较底层、也最灵活:
你自己构造一个 Request 对象,想怎么配 header、body、URL 都行,然后丢给会话去发。
3.1 基本流程
- 构造
rcp.Request(url, method) rcp.createSession()session.fetch(request),拿到Promise<Response>
3.2 示例:最简单的 fetch GET
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 1. 构造请求
const kHttpServerAddress = "https://www.example.com/fetch";
const request = new rcp.Request(kHttpServerAddress, 'GET');
// 2. 创建会话
const session = rcp.createSession();
// 3. 发请求
session.fetch(request)
.then((rep: rcp.Response) => {
console.info(`Response succeeded: ${rep}`);
})
.catch((err: BusinessError) => {
console.error(
`Response err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`
);
});
实际项目里,Request 还能设置:
- 请求头:
request.headers = {...} - 请求体:
request.content = ...(配合Form/MultipartForm/ 自定义内容)
fetch 更像是"通用版本",后面那堆 get/post/put/... 算是常用 HTTP 方法的快捷封装。
4. GET:最常用的读取数据方式
4.1 接口说明
get(url: URLOrString, destination?: ResponseBodyDestination): Promise<Response>
url:要请求的地址destination:响应体目标(可选,比如流式处理或者指定存储方式)- 返回:
Promise<Response>
4.2 示例:发一个 GET 请求
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 1. 请求地址(示例),实际按自己的接口来
const getURL = "http://www.example.com/get";
// 2. 创建会话
const session = rcp.createSession();
// 3. 发 GET 请求
session.get(getURL)
.then((response: rcp.Response) => {
console.info(`Response succeeded: ${response}`);
// 这里可以继续处理 response.body / response.headers / response.statusCode
})
.catch((err: BusinessError) => {
console.error(
`Response err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`
);
});
特点:
- GET 默认把参数拼在 URL 上(比如
?id=1&name=xxx), - 适合:查数据、拉配置、获取列表 / 详情 等。
5. POST:提交数据的主力请求
5.1 接口说明
post(
url: URLOrString,
content?: RequestContent,
destination?: ResponseBodyDestination
): Promise<Response>
content:要发给服务器的数据(表单 / JSON / file 等,都可以封进RequestContent)destination:响应体处理方式(可选)
5.2 示例:用 fields 提交简单表单数据
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
// URL 示例
const postURL = "https://www.example.com";
// 构造要提交的内容
const postContent: rcp.RequestContent = {
fields: {
'key1': 'value1',
'key2': 'value2',
'key3': 'value3'
}
};
// 创建会话
const session = rcp.createSession();
// 发 POST 请求
session.post(postURL, postContent)
.then((response: rcp.Response) => {
console.info(`Response headers: ${JSON.stringify(response.headers)}`);
console.info(`Response status: ${JSON.stringify(response.statusCode)}`);
console.info(`Request content: ${JSON.stringify(postContent)}`);
})
.catch((err: BusinessError) => {
console.error(
`Response err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`
);
});
常见场景:
- 创建资源(新增)
- 提交表单(登录、注册、下单等)
- 向后端发送 JSON 数据、表单数据
6. PUT:更新资源的幂等请求
PUT 的语义:更新指定资源(通常是全量更新),幂等 ------ 连续调用多次,结果应该是一样的。
6.1 接口说明
put(
url: URLOrString,
content?: RequestContent,
destination?: ResponseBodyDestination
): Promise<Response>
6.2 示例:用 PUT 更新资源
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 1. 创建会话
const session = rcp.createSession();
// 2. 要提交的内容,写法和 POST 类似
const putContent: rcp.RequestContent = {
fields: {
'key1': 'value1',
'key2': 'value2',
'key3': 'value3'
}
};
// 3. 发 PUT 请求
session.put("http://www.example.com/put", putContent)
.then((response: rcp.Response) => {
console.info(`Response succeeded: ${response}`);
})
.catch((err: BusinessError) => {
console.error(
`Response err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`
);
});
我自己的使用习惯:
- 新增用 POST
- 整体更新用 PUT
- 局部更新(比如只改一个字段)如果接口支持,会用 PATCH(如果后面有对应封装的话)
7. HEAD:只要响应头,不要内容
HEAD 很适合这种场景:
- 想知道文件多大、最后更新时间等元信息;
- 想检查资源是否存在 / 是否有权限;
- 想探测接口状态,但是不想拉整个响应体。
7.1 接口说明
head(url: URLOrString): Promise<Response>
7.2 示例:发一个 HEAD 请求
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 1. 创建会话
const session = rcp.createSession();
// 2. 发 HEAD 请求
session.head("http://www.example.com/head")
.then((response: rcp.Response) => {
console.info(`Response succeeded: ${response}`);
// 关注 response.headers 就够了
})
.catch((err: BusinessError) => {
console.error(
`Response err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`
);
});
8. DELETE:删除远端资源
DELETE 语义:删除指定 URL 对应的资源。
8.1 接口说明
delete(url: URLOrString): Promise<Response>
8.2 示例:DELETE 请求
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 1. 创建会话
const session = rcp.createSession();
// 2. 发 DELETE 请求
session.delete("http://www.example.com/delete")
.then((response: rcp.Response) => {
console.info(`Response succeeded: ${response}`);
})
.catch((err: BusinessError) => {
console.error(
`Response err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`
);
});
常见用在:
- 删除某个记录
- 取消某个预约/订阅
- 清理服务端的一些临时资源
9. Form:发送简单表单数据(RequestContent)
当我们在 HTTP 请求中要发表单数据时,可以用 Form 来生成一个 RequestContent,直接丢给 Request。
9.1 版本点
- 从 6.0.1(21) 开始,
Form支持keys属性,
可以用来控制 表单中 Key 的发送顺序。
9.2 示例:使用 Form 发送简单表单
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 1. 创建 Form 表单数据
const simpleForm = new rcp.Form({
"key1": "value1",
"key2": "value2",
});
// 2. 指定发送顺序
// - 指定后:按 ["key2", "key1"] 的顺序发送
// - 不在列表中的 key 不会被发送
simpleForm.keys = ["key2", "key1"];
// 3. 创建 Request
let req = new rcp.Request("http://example.com");
req.content = simpleForm;
// 4. 创建会话 + 发 fetch 请求
try {
const session = rcp.createSession();
session.fetch(req)
.then((resp: rcp.Response) => {
console.info(`Response succeeded: ${JSON.stringify(resp)}`);
session.close();
})
.catch((err: BusinessError) => {
console.error(
`Response err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`
);
session.close();
});
} catch (err: any) {
console.error(
`createSession err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`
);
}
这里有一个小细节:
如果指定了
keys:
- 只会发送
keys里出现的字段,- 并且按照
keys的顺序发送。如果不指定
keys:
- 默认按各个 key 的 hash 顺序发送。
这个在一些后端"严格按顺序解析"或者"签名校验里包含顺序"的场景特别有用。
10. MultipartForm:发送多部分表单(文件上传等)
如果要发的是 带文件 / 多部分的数据 ,就要上 MultipartForm,典型场景就是文件上传。
10.1 版本点
同样是从 6.0.1(21) 开始,MultipartForm 也支持 keys 来指定发送顺序。
10.2 示例:使用 MultipartForm 发送多部分数据
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 1. 创建 MultipartForm 数据
const multiForm = new rcp.MultipartForm({
"key1": "value1",
"key2": "value2",
"key3": "value3",
// 实际项目里这里可以放文件、二进制内容等
});
// 2. 指定发送顺序
multiForm.keys = ["key3", "key1", "key2"];
// 3. 创建 Request
let req = new rcp.Request("http://example.com");
req.content = multiForm;
// 4. 创建会话 + 发请求
try {
const session = rcp.createSession();
session.fetch(req)
.then((resp: rcp.Response) => {
console.info(`Response succeeded: ${JSON.stringify(resp)}`);
session.close();
})
.catch((err: BusinessError) => {
console.error(
`Response err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`
);
session.close();
});
} catch (err: any) {
console.error(
`createSession err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`
);
}
可以把它理解成:
Form:纯 key-value 文本表单MultipartForm:可以混合文本 + 文件的多段表单(对应multipart/form-data场景)
11. 我自己的几点实战小结
最后,用几条"以后写代码要记得注意"的点收个尾:
- 所有请求都基于 Session
- 统一入口:
const session = rcp.createSession() - 用完记得
session.close(),特别是频繁请求的场景。
- 统一入口:
- 简单就用 get/post,复杂用 fetch + Request
- GET / POST / PUT / HEAD / DELETE 适合常规接口;
- 有特殊 header / 复杂 body / 特殊目的时,构造一个
Request+session.fetch()会更自在。
- 错误处理一定要写到 catch 里
- Promise 风格:
then(...).catch((err: BusinessError) => { ... }) err.code+err.message是排查问题的关键。
- Promise 风格:
- Form / MultipartForm 的 keys 顺序不要忽略
- 遇到和后端签名、网关校验这些"对顺序敏感"的情况时,
simpleForm.keys/multiForm.keys非常好用。
- 记得设备约束
- 这套能力支持 Phone / 2in1 / Tablet / Wearable,
- TV 要从 5.1.1(19) 开始才支