一、为什么要对http请求进行封装?
在我看来二次封装有一下几点好处
- 代码封装之后,开发人员只用关注业务层面的东西,不用去过多浪费时间在接口请求数据处理上。
- 封装之后代码更加简洁,通俗易懂,方便后期维护,统一管理。
- 对经验不足的开发人员友好,只需要依葫芦画瓢,参照之前的例子就可以进行开发。
- 随着团队规模变大,代码封装之后,减少代码冗余,防止屎山代码。
- 统一处理token修改配置项,统一对数据错误和数据返回进行处理提示等。
二、注意事项
- 使用HTTP数据请求需要申请ohos.permission.INTERNET权限权
- 此次封装功能并没有像axios 里面一样有响应拦截器和请求拦截前。
- 没有取消重复请求、错误请求重连的功能,所以只适合较小的项目。
三、开始进行封装
1. 创建请求实体类
在ets/common/utils下创建文件request.ets
import http from '@ohos.net.http';
export interface httpConfig{
url:string;
method:http.RequestMethod;
timeOut?: number;
data?: string | Object | ArrayBuffer;
header?: Object;
expectDataType?: http.HttpDataType;
}
interface HttpResponse{
code:string|number;
message:string;
data:string|Object|unknown[]
}
export default (config: httpConfig): Promise<HttpResponse>=> {
// 创建请求实例
const service = http.createHttp();
}
2. 对请求实体类进行 Promise 封装
这里面加入了Authorization 身份信息、 Content-Type响应方式、connectTimeout连接超时等 自己需要根据实际业务情况更换
import http from '@ohos.net.http';
export interface httpConfig{
url:string;
method:http.RequestMethod;
timeOut?: number;
data?: string | Object | ArrayBuffer;
header?: Object;
expectDataType?: http.HttpDataType;
}
interface HttpResponse{
code:string|number;
message:string;
data:string|Object|unknown[]
}
export default (config: httpConfig): Promise<HttpResponse>=> {
// 创建请求实例
const service = http.createHttp();
//请求地址
const url ='http://XXX.XXX' +config.url;
return new Promise((resolve, reject) => {
service.request(
url,
{
method: config.method,
expectDataType: config.expectDataType, //数据类型
header: {
"Content-Type":"application/json",
//header中存放身份信息
Authorization:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
...config.header,
},
extraData: config.data,
readTimeout:config.timeOut|| 50000,
connectTimeout:config.timeOut|| 50000
},
(err, response)=>{
if (!err && response.responseCode === 200) { //请求200
if (typeof response.result === 'string') {
const resData= JSON.parse(response.result)
if(resData.code==2001){ //接口状态成功
resolve(resData)
}else{
// 接口约定好的状态码 例如登录过期 等等
reject(response)
}
} else {
//接口返回数据异常
reject(response)
}
} else {
// 状态码异常 例如 404 502 503 等等
// 请求失败通常是后端问题或者网络问题
reject(response)
}
}
)
})
}
3. 封装一个公共提示框
在 ets/common/utils 下创建文件DialogUtils.ets 内容如下
/**
* This is a pop-up window tool class, which is used to encapsulate dialog code.
* Developers can directly invoke the methods in.
*/
export class DialogUtils {
/**
* 轻提示
*/
toast(content:{message:string}) {
AlertDialog.show({
message: content.message,
alignment: DialogAlignment.Center,
primaryButton: {
value: '取消',
action: () => {
}
},
secondaryButton: {
value: '确认',
action: () => {
}
}
});
}
}
export default new DialogUtils();
4. 在请求里面多错误状态进行相应判断处理提示
import http from '@ohos.net.http';
import DialogUtils from "./DialogUtils"
export interface httpConfig{
url:string;
method:http.RequestMethod;
timeOut?: number;
data?: string | Object | ArrayBuffer;
header?: Object;
expectDataType?: http.HttpDataType;
}
interface HttpResponse{
code:string|number;
message:string;
data:string|Object|unknown[]
}
export default (config: httpConfig): Promise<HttpResponse>=> {
// 创建请求实例
const service = http.createHttp();
//请求地址
const url ='http://XXX.XXX' +config.url;
return new Promise((resolve, reject) => {
service.request(
url,
{
method: config.method,
expectDataType: config.expectDataType, //数据类型
header: {
"Content-Type":"application/json",
//header中存放身份信息
Authorization:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
...config.header,
},
extraData: config.data,
readTimeout:config.timeOut|| 50000,
connectTimeout:config.timeOut|| 50000
},
(err, response)=>{
if (!err && response.responseCode === 200) { //请求200
if (typeof response.result === 'string') {
const resData= JSON.parse(response.result)
if(resData.code==2001){ //接口状态成功
resolve(resData)
}else{
// 接口约定好的状态码 例如登录过期 等等
DialogUtils.toast({message:'身份信息已失效,请重新登录'})
reject(response)
}
} else {
//接口返回数据异常
DialogUtils.toast({message:'网络请求错误,请稍后再试'})
reject(response)
}
} else {
// 状态码异常 例如 404 502 503 等等
// 请求失败通常是后端问题或者网络问题
checkStatus(response.responseCode)
reject(response)
}
}
)
})
function checkStatus(status: number): void {
let errMessage = '';
switch (status) {
case 400:
errMessage = '网络请求超时!';
break;
case 401:
errMessage = '用户没有权限(令牌、用户名、密码错误)!';
break;
case 403:
errMessage = '用户得到授权,但是访问是被禁止的!';
break;
case 404:
errMessage = '网络请求错误,未找到该资源!';
break;
case 405:
errMessage = '网络请求错误,请求方法未允许!';
break;
case 408:
errMessage = '网络请求超时!';
break;
case 500:
errMessage = '服务器错误,请联系管理员!';
break;
case 501:
errMessage = '网络未实现!';
break;
case 502:
errMessage = '网络错误!';
break;
case 503:
errMessage = '服务不可用,服务器暂时过载或维护!';
break;
case 504:
errMessage = '网络超时!';
break;
case 505:
errMessage = 'http版本不支持该请求!';
break;
default:
}
if (errMessage) {
// 进行错误提示
console.log('errMessage',errMessage)
DialogUtils.toast({message:errMessage})
}
}
}
5. 封装业务接口
在ets/common/api下创建文件 index.ets 自己要根据实际业务进行调整这里只是示例 ,我在这里封装了一个 GET 一个POST 请求。
import request from "../utils/request";
import http from '@ohos.net.http';
// 数据列表
export const listByCondition = (data:Record<string, string|number>) => {
return request({
url: "/wms/isoftstone-form-onlineoperation/listByCondition",
method: http.RequestMethod.POST,
data:data
});
};
// 字典列表
export const dictList = (data:Record<string, string|number>) => {
return request({
url: "/wms/dict/list2",
method: http.RequestMethod.GET,
data:data
});
};
6. 项目中使用且请求接口
在ets/pages/Index.ets 页面写入以下代码进行测试
import {listByCondition,dictList} from "../common/api/index"
@Entry
@Component
struct Index {
@State listData:unknown[] = [];//数据列表
@State dicData:unknown[] = [];//字典列表
// 获取数据列表
async getListByCondition(){
let res = await listByCondition({
"tableName":"cd_warehouse",
"columnName":"park_code",
"columnValue":"DCYQ01",
"filterType":1
});
this.listData = res.data as unknown[];
};
// 获取字典
async getDictList(){
let res = await dictList({
"code":"SYS_WMS_WORK_TYPE",
});
this.dicData = res.data as unknown[];
};
onPageShow(){
this.getListByCondition();
this.getDictList();
};
build() {
Column(){
Column(){
ForEach(this.listData, (item) => {
Row(){
Text(item.wh_code)
Text(item.cdwh_name)
}
})
}
Column(){
ForEach(this.dicData, (item) => {
Row(){
Text(item.value)
Text(item.label)
}
})
}
}
.height('100%')
}
}
到这里对http请求二次封装就已经基本完成,本文只做了一些简单封装,主要是按照前端开发习惯进行封装,大家有需要可以参考学习。
最后
小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,不同的角度的问了一些问题,我明显感觉到一点,那就是许多人参与鸿蒙开发,但是又不知道从哪里下手,因为资料太多,太杂,教授的人也多,无从选择。有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)文档用来跟着学习是非常有必要的。
为了确保高效学习,建议规划清晰的学习路线,涵盖以下关键阶段:
鸿蒙(HarmonyOS NEXT)最新学习路线
该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案
路线图适合人群:
IT开发人员:想要拓展职业边界
零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能。
技术提升/进阶跳槽:发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术
2.视频学习教程+学习PDF文档
HarmonyOS Next 最新全套视频教程
纯血版鸿蒙全套学习文档(面试、文档、全套视频等)
总结
参与鸿蒙开发,你要先认清适合你的方向,如果是想从事鸿蒙应用开发方向的话,可以参考本文的学习路径,简单来说就是:为了确保高效学习,建议规划清晰的学习路线