一、封装http请求
官方文档里的http开发指南比较全面,下面我来讲解主要的步骤。
1、创建resultVO接口
前端发送请求后,后端返回的数据一般是如下格式:code--响应状态码;msg--响应信息;data--响应数据。响应数据data一般有多种类型,这里用泛型T接收,外部调用时,再指定T的类型。ArkTS是TypeScipt的超集,一般TS有的,ArkTS也有。所以ArkTS也支持泛型。
/*
* resultVO接口
* @code 响应码
* @msg 响应信息
* @data 响应数据
*/
export default interface resultVO<T>{
code: number
msg: string
data: T
}
2、创建requestParams接口
此接口用于规范调用http请求时的参数。
import { http } from '@kit.NetworkKit'
/*
* requestParams接口
* @url 必填 访问地址 (后端api访问地址)
* @method 选填(默认get) 请求方法 (get、post...)
* @extraData 选填(默认undefined ) 请求参数
*/
export interface requestParams{
url: string
method?: http.RequestMethod
extraData?: object
}
3、创建request文件,封装http请求
3.1 编写request方法
request方法需传入请求参数(requestParams接口),并返回一个Promise对象,该对象里面是resultVO类型的数据。
/*
* request方法
* @params requestParams接口类型
* @@return Promise<resultVO<T>>
*/
export const request = async <T>(params: requestParams): Promise<resultVO<T>> => {
/*
* @resolve 请求成功
* @reject 请求失败
*/
return new Promise(async (resolve, reject) => {
})
}
3.2 返回Promise对象前,先获取一下关键参数
如果是本地模拟器访问本地的SpringBoot服务器,基地址为你所使用的电脑,它的IPv4地址。移动端项目和Vue项目不同,Vue项目的基地址一般是127.0.0.1,这个需要注意。我们这里把基地址设置成一个常量。要修改是,去常量类里面修改,提高代码的维护性。
token可以使用首选项进行存储和调用。首选项的知识可以看我的另外一篇文章:封装用户首选项
请求头一般是json类型,如有其他需求,可以更改。这个一般是和后端协调决定。如果自己做课设或者毕设,这里传一个token进来就可以了。
// 基地址。如果用本地模拟器访问,基地址一般为 “http://本机的IPv4地址:8080”
const baseURL: string = CommonConstants.BASE_URL
// 创建一个HttpRequest对象 -- 不可复用,一个httpRequest对象对应一个http请求
let httpRequest = http.createHttp()
// 获取token
let token: preferences.ValueType = await PreferenceUtil.getPreferenceValue(
CommonConstants.TOKEN, CommonConstants.NULL_TOKEN
)
// 完整请求地址
let requestUrl = baseURL + params.url
// 发起请求可选参数的类型和取值范围。
let options: http.HttpRequestOptions = {
// 请求类型,不传默认get
method: params.method ?? http.RequestMethod.GET,
// 请求头
// 做课设、毕设之类的,'Content-Type'默认'application/json'就好
// 请求头只用携带一个token,用于身份的校验
header: {
'Content-Type': 'application/json',
token
},
// 请求参数,不传默认undefined
extraData: params.extraData ?? undefined,
// 必填,不知道是不是bug,不填object类型,就会拿不到后端数据,和官方文档不一样
// 也可能是我后端接口的问题。----------这里存疑----------
expectDataType: http.HttpDataType.OBJECT
}
3.3 发送request请求
获取所需的参数之后,我们就可以发起request请求了,具体如下。请求成功后,记得销毁httpRequest对象,释放内存。
/*
* @resolve 请求成功
* @reject 请求失败
*/
return new Promise(async (resolve, reject) => {
/*
* 发送http请求
* @url 后端api完整地址
* @options 发起请求的可选参数
* @callback 回调函数
*/
httpRequest.request(
requestUrl,
options,
(err, data) => {
if (!err) {
// 处理请求成功的逻辑
// 获得后端返回过来的resultVO
const res = data.result as resultVO<T>
} else {
// 处理请求失败的逻辑
promptAction.showToast({message: CommonConstants.REQUEST_ERROR})
console.error('error:' + JSON.stringify(err))
reject(err)
}
// 销毁httpRequest对象
httpRequest.destroy()
}
)
})
3.4 根据业务需要处理请求后的逻辑
例1:拦截token过期
// token过期
if(res.code == CommonConstants.TOKEN_INVALIDATION){
promptAction.showToast({message: CommonConstants.TOKEN_INVALIDATION_MSG})
//清空历史页面
router.clear()
//跳转到登录页
router.replaceUrl({
url: CommonConstants.LOGIN_PAGE_URL
})
return
}
例2:处理正确状态码
// 判断响应码
if(res.code == CommonConstants.CODE_SUCCESS){
// 返回想要的的结果
resolve(res)
}else {
promptAction.showToast({message: res.msg})
return
}
DD一下:欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。
`欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。`
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案)
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......
二、完整文件代码
文件1:常量类
export class CommonConstants {
static readonly BASE_URL: string = 'http://192.168.31.160:8080'
// global data key
static readonly G_STORE: string = 'GreenTreasureStore';
static readonly TOKEN: string = 'TOKEN'
static readonly NULL_TOKEN: string = null
static readonly TOKEN_INVALIDATION : number = 401
static readonly CODE_SUCCESS : number = 1
static readonly TOKEN_INVALIDATION_MSG : string = 'token过期,请重新登录'
static readonly REQUEST_ERROR : string = '请求失败'
static readonly LOGIN_PAGE_URL : string = '/pages/Login/Index'
}
文件2:resultVO接口
/*
* resultVO接口
* @code 响应码
* @msg 响应信息
* @data 响应数据
*/
export default interface resultVO<T>{
code: number
msg: string
data: T
}
文件3:requestParams接口
import { http } from '@kit.NetworkKit'
/*
* requestParams接口
* @url 必填 访问地址 (后端api访问地址)
* @method 选填(默认get) 请求方法 (get、post...)
* @extraData 选填(默认undefined ) 请求参数
*/
export interface requestParams{
url: string
method?: http.RequestMethod
extraData?: object
}
文件4:request文件
import { http } from '@kit.NetworkKit'
import { preferences } from '@kit.ArkData'
import PreferenceUtil from '../utils/PreferencesUtil'
import resultVO from '../common/impl/resultVO'
import { CommonConstants } from '../constants/CommonConstants'
import { requestParams } from '../common/impl/requestParams'
import { promptAction, router } from '@kit.ArkUI'
/*
* request方法
* @params requestParams接口类型
* @@return Promise<resultVO<T>>
*/
export const request = async <T>(params: requestParams): Promise<resultVO<T>> => {
// 基地址。如果用本地模拟器访问,基地址一般为 “http://本机的IPv4地址:8080”
const baseURL: string = CommonConstants.BASE_URL
// 创建一个HttpRequest对象 -- 不可复用,一个httpRequest对象对应一个http请求
let httpRequest = http.createHttp()
// 获取token
let token: preferences.ValueType = await PreferenceUtil.getPreferenceValue(
CommonConstants.TOKEN, CommonConstants.NULL_TOKEN
)
// 完整请求地址
let requestUrl = baseURL + params.url
// 发起请求可选参数的类型和取值范围。
let options: http.HttpRequestOptions = {
// 请求类型,不传默认get
method: params.method ?? http.RequestMethod.GET,
// 请求头
// 做课设、毕设之类的,'Content-Type'默认'application/json'就好
// 请求头只用携带一个token,用于身份的校验
header: {
'Content-Type': 'application/json',
token
},
// 请求参数,不传默认undefined
extraData: params.extraData ?? undefined,
// 必填,不知道是不是bug,不填object类型,就会拿不到后端数据,和官方文档不一样
// 也可能是我后端接口的问题。----------这里存疑----------
expectDataType: http.HttpDataType.OBJECT
}
/*
* @resolve 请求成功
* @reject 请求失败
*/
return new Promise(async (resolve, reject) => {
/*
* 发送http请求
* @url 后端api完整地址
* @options 发起请求的可选参数
* @callback 回调函数
*/
httpRequest.request(
requestUrl,
options,
(err, data) => {
if (!err) {
// 处理请求成功的逻辑
console.info('httpRequest','code:' + JSON.stringify(data.result['code']))
console.info('httpRequest','msg:' + JSON.stringify(data.result['msg']))
console.info('httpRequest','data:' + JSON.stringify(data.result['data']))
// 获得后端返回过来的resultVO
const res = data.result as resultVO<T>
// token过期
if(res.code == CommonConstants.TOKEN_INVALIDATION){
promptAction.showToast({message: CommonConstants.TOKEN_INVALIDATION_MSG})
//清空历史页面
router.clear()
//跳转到登录页
router.replaceUrl({
url: CommonConstants.LOGIN_PAGE_URL
})
return
}
// 判断响应码
if(res.code == CommonConstants.CODE_SUCCESS){
// 返回想要的的结果
resolve(res)
}else {
promptAction.showToast({message: res.msg})
return
}
} else {
// 处理请求失败的逻辑
promptAction.showToast({message: CommonConstants.REQUEST_ERROR})
console.error('error:' + JSON.stringify(err))
reject(err)
}
// 销毁httpRequest对象
httpRequest.destroy()
}
)
})
}
三、发送request请求
1、开启网络权限
想要发送http请求,必须开启网络权限。网络权限开启步骤如下:
1.1 找到文件entry/src/main/module.json5
1.2 进入文件module.json5,在【module】的下一级,加上:
"requestPermissions":[
{
"name" : "ohos.permission.GET_NETWORK_INFO",
},
{
"name" : "ohos.permission.INTERNET",
}
],
2、测试登录请求
可以自己找一些后端接口进行测试。这里是笔者自己写的后端接口。后端接口的编写本文暂时不讲。读者可以自己试着写写看。
2.1 创建LoginDTO接口
该接口规范登录请求的参数
export interface LoginDTO{
userPhone: string
password: string
}
2.2 测试
import { LoginDTO } from '../common/dto/LoginDTO'
import { request } from '../utils/request';
import { http } from '@kit.NetworkKit';
const login = (loginDto: LoginDTO) => {
return request<string>({
url: `/user/api/login?userPhone=${loginDto.userPhone}&password=${loginDto.password}`,
method: http.RequestMethod.POST,
})
}
@Entry
@Component
struct Index {
async aboutToAppear() {
const res = await login({userPhone: '13652576888',password:'123456'})
}
build() {
}
}
2.3 结果
在鸿蒙HarmonyOS应用开发中,网络请求是不可或缺的一部分。HarmonyOS提供了http模块来处理HTTP请求,并且支持使用Promise和异步回调来处理请求结果,使得网络请求的处理更加简洁和高效。
DD一下:欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。
`欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。`
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案)
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......
Promise与异步回调
Promise是JavaScript中用于处理异步操作的一种对象,它可以代表一个异步操作的最终完成或失败,并可以链式调用,使得异步代码的编写更加清晰。在HarmonyOS中,我们可以使用Promise来处理http模块的异步回调。
使用Promise处理Http请求
下面是一个使用Promise处理HTTP请求的示例代码:
async send(): Promise<http.HttpResponse> {
return new Promise<http.HttpResponse>((resolve, reject) => {
this.httpRequest.request("http://www.baidu.com",
{
method: http.RequestMethod.GET,
header: {
'Content-Type': 'application/json'
},
expectDataType: http.HttpDataType.STRING,
usingCache: true,
priority: 1,
connectTimeout: 60000,
readTimeout: 60000,
usingProtocol: http.HttpProtocol.HTTP1_1
}, (err, data) => {
if (!err) {
this.httpRequest.off('headersReceive');
this.httpRequest.destroy();
resolve(data);
} else {
this.httpRequest.off('headersReceive');
this.httpRequest.destroy();
reject(resolve(data));
}
});
});
}
在这个示例中,我们定义了一个send方法,它返回一个Promise对象。在Promise的构造函数中,我们发起了HTTP请求,并在回调函数中处理请求结果。如果请求成功,我们取消订阅HTTP响应头事件,销毁请求对象,并调用resolve方法传递数据;如果请求失败,我们同样取消订阅事件和销毁对象,并调用reject方法传递错误信息。
使用then和catch处理结果
一旦我们有了返回Promise的异步操作,我们就可以使用then和catch方法来处理结果。下面是如何使用then和catch来处理send方法的结果:
http.send().then((data: http.HttpResponse) => {
console.log("Received data:", data.result.toString());
}).catch((error: string) => {
console.error("Error occurred:", error);
});
在这个代码片段中,我们调用了send方法,并使用then方法来处理成功的结果,使用catch方法来处理失败的情况。这样,我们就可以优雅地处理网络请求的各种情况,而不需要嵌套的回调函数。
注意事项
- 在使用Promise时,确保正确处理异步操作的成功和失败,避免未处理的Promise导致的问题。
- 在请求完成后,记得取消订阅相关事件并销毁请求对象,以释放资源。
- 根据实际业务需求,合理设置请求的超时时间和其他参数。
结语
通过使用Promise和异步回调,我们可以更加优雅地处理HarmonyOS中的HTTP请求。这种方式不仅提高了代码的可读性,还使得错误处理更加直观。在实际开发中,合理运用Promise可以大大提升开发效率和代码质量。