一、为什么要对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)学习路径和一些资料的整理供小伙伴学习
点击领取→纯血鸿蒙Next全套最新学习资料(安全链接,放心点击)
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
一、鸿蒙(HarmonyOS NEXT)最新学习路线
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)…等技术知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
二、HarmonyOS Next 最新全套视频教程
三、《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
- ArkTS语言
- 安装DevEco Studio
- 运用你的第一个ArkTS应用
- ArkUI声明式UI开发
- .……
《鸿蒙开发进阶》
- Stage模型入门
- 网络管理
- 数据管理
- 电话服务
- 分布式应用开发
- 通知与窗口管理
- 多媒体技术
- 安全技能
- 任务管理
- WebGL
- 国际化开发
- 应用测试
- DFX面向未来设计
- 鸿蒙系统移植和裁剪定制
- ……
《鸿蒙进阶实战》
- ArkTS实践
- UIAbility应用
- 网络案例
- ……
四、大厂面试必问面试题
五、鸿蒙南向开发技术
六、鸿蒙APP开发必备
七、鸿蒙生态应用开发白皮书V2.0PDF
完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。