一、前言
本文采用axios 网络请求框架进行封装,便于后续开发,参考文档。
API : API Version 12 Beta5
Dev : 5.0.3.700
axios: “2.2.0”
二、详细代码
1.在项目的oh-package.json5文件中引入axios依赖
"@ohos/axios": "2.2.0"
2.在主App的module.json5增加网络请求权限
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
},
],
3.主要工具类HttpUtil
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import axios, { AxiosError, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig, Method } from '@ohos/axios';
import { Log } from '../utils/Log';
import { systemDateTime } from '@kit.BasicServicesKit';
import ResponseResult from './ResponseResult';
import { StringBuilder } from '../utils/StringBuilder';
import { HttpConstant } from './HttpContent';
const timeout = 20000 // 20s超时
// const baseUrl = 'https://api-harmony-teach.itheima.net/hm/'
const baseUrl = HttpConstant.BaseUrl
export function httpDefaultSetting() {
// default settings
axios.defaults.baseURL = baseUrl;
axios.defaults.timeout = timeout;
// default headers
// axios.defaults.headers.common['Client-Type'] = 'xxx';
axios.defaults.headers.common['Client-Version'] = '1.0.4';
axios.defaults.headers.common['Os'] = 'hmos';
// axios.defaults.headers.common['Token'] = 'xxx';
// for post
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
// 添加请求拦截器
axios.interceptors.request.use((config: InternalAxiosRequestConfig) => {
return transRequest(config);
}, (error: AxiosError) => {
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use((response: AxiosResponse) => {
return transResponse(response);
}, (error: AxiosError) => {
return Promise.reject(error);
});
}
/**
* 请在这里处理请求体的拦截器操作逻辑
*
*/
function transRequest(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
try {
let millis = systemDateTime.getTime();
// config.headers['t'] = millis - Constant.offsetTime; // 同步时间
// 增加验签逻辑
// 验签可以仅在需要的请求中增加验签,通过增加特定的header属性来区分
} finally {
return config;
}
}
/**
* 请在这里处理请求结果的拦截器操作逻辑
*
*/
function transResponse(response: AxiosResponse): AxiosResponse {
try {
let millis = systemDateTime.getTime();
if (lt != 0 && millis - lt < 60000) {
return response;
} // 可选,性能优化 1分钟内避免重复处理
lt = millis
// let headers: HashMap<string, ESObject> = JSON.parse(JSON.stringify(response.headers));
// let t: number = headers['servertimestamp'];
// Constant.offsetTime = millis - t;
return response;
} catch (e) {
console.error(e)
return response;
}
}
let lt = 0
/**
* Initiates an HTTP request to a given URL.
*
* @param url URL for initiating an HTTP request.
* @param params Params for initiating an HTTP request.
*/
export function httpGet<D>(url: string, params?: ESObject, headers?: ESObject): Promise<D> {
return new Promise<D>((resolve: Function, reject: Function) => {
let startTime = systemDateTime.getTime()
axios.get<ResponseResult, AxiosResponse<ResponseResult>, null>(url, {
headers: headers,
// 指定请求超时的毫秒数(0 表示无超时时间)
timeout: timeout, // 超时
// `connectTimeout` 指定请求连接服务器超时的毫秒数(0 表示无超时时间)
// 如果请求连接服务器超过 `connectTimeout` 的时间,请求将被中断
// connectTimeout: 60000, // 文档和代码不一致,代码中无法设置连接超时时间
params: params,
})
.then((response: AxiosResponse<ResponseResult>) => {
let duration = (systemDateTime.getTime() - startTime).toString()
Log.info(`httpGet: Success. duration=${duration} url:${response.config.baseURL}${response.config.url}\n
config=${JSON.stringify(response.config)}\n
parmar=${JSON.stringify(response.config.params)}\n
status=${response.status}\n
headers${JSON.stringify(response.headers)}\n
data=${JSON.stringify(response.data)}`);
if (isSuccess(response)) {
if (isResultSuccess(response.data)) {
resolve(response.data.data);
} else {
const e: Error = { name: `${response.data.errorCode}`, message: `${response.data.description}` }
reject(e);
}
} else {
const e: Error = { name: `${response.status}`, message: `${response.statusText}` }
reject(e);
}
})
.catch((reason: AxiosError) => {
Log.info(`httpGet: Success. url:${reason.response?.config.baseURL}${reason.response?.config.url}\n`)
Log.error(JSON.stringify(reason));
reject(reason)
})
});
}
function getRequestFormData(data?: ESObject): string | undefined {
if (data == undefined) {
return undefined;
}
let sb = new StringBuilder();
Object.keys(data).forEach((key: string) => {
sb.append(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
})
const formData = sb.build('&');
Log.info("getRequestFormData: formData=" + formData);
return formData;
}
function buildPostRequestHeader(isFormUrlencoded: boolean,
headers?: Record<ESObject, ESObject>): Record<ESObject, ESObject> {
if (headers != null) {
headers['Content-Type'] = isFormUrlencoded ? 'application/x-www-form-urlencoded' : 'application/json'
return headers
}
return {
'Content-Type': isFormUrlencoded ? 'application/x-www-form-urlencoded' : 'application/json',
}
}
/**
* Initiates an HTTP request to a given URL.
*
* @param url URL for initiating an HTTP request.
* @param params Params for initiating an HTTP request.
*/
// o: { [s: string]: ESObject }
export function httpPost<D>(url: string, isFormUrlencoded: boolean = true, data?: ESObject, params?: ESObject,
headers?: ESObject): Promise<D> {
// Log.info( "httpPost: ");
return new Promise<D>((resolve: Function, reject: Function) => {
let startTime = systemDateTime.getTime()
axios.post(url, isFormUrlencoded ? getRequestFormData(data) : data, {
headers: buildPostRequestHeader(isFormUrlencoded, headers),
// 指定请求超时的毫秒数(0 表示无超时时间)
timeout: timeout, // 超时
// `connectTimeout` 指定请求连接服务器超时的毫秒数(0 表示无超时时间)
// 如果请求连接服务器超过 `connectTimeout` 的时间,请求将被中断
// connectTimeout: 60000, // 文档和代码不一致,代码中无法设置连接超时时间
params: params,
})
.then((response: AxiosResponse<ResponseResult>) => {
let duration = (systemDateTime.getTime() - startTime).toString()
Log.info(`httpPost: Success. duration=${duration} url:${response.config.baseURL}${response.config.url}\n
config=${JSON.stringify(response.config)}\n
status=${response.status}\n
body=${response.config.data}\n
headers${JSON.stringify(response.headers)}\n
data=${JSON.stringify(response.data)}`);
if (isSuccess(response)) {
if (isResultSuccess(response.data)) {
resolve(response.data.data);
} else {
const e: Error = { name: `${response.data.errorCode}`, message: `${response.data.description}` }
reject(e);
}
} else {
const e: Error = { name: `${response.status}`, message: `${response.statusText}` }
reject(e);
}
})
.catch((reason: AxiosError) => {
Log.error(JSON.stringify(reason));
reject(reason)
})
});
}
/**
* Initiates an HTTP request to a given URL.
*
* @param url URL for initiating an HTTP request.
* @param params Params for initiating an HTTP request.
*/
export function httpRequest<D>(url: string, method?: Method | string, data?: D,
config?: AxiosRequestConfig<D>): Promise<ResponseResult> {
// Log.info( "httpRequest: ");
return new Promise<ResponseResult>((resolve: Function, reject: Function) => {
let startTime = systemDateTime.getTime()
axios.request<ResponseResult, AxiosResponse<ResponseResult>, D>({
url: url,
method: method,
baseURL: baseUrl,
headers: config?.headers,
// 指定请求超时的毫秒数(0 表示无超时时间)
timeout: timeout, // 超时
// `connectTimeout` 指定请求连接服务器超时的毫秒数(0 表示无超时时间)
// 如果请求连接服务器超过 `connectTimeout` 的时间,请求将被中断
// connectTimeout: 60000, // 文档和代码不一致,代码中无法设置连接超时时间
params: config?.params,
data: data ?? config?.data
})
.then((response: AxiosResponse<ResponseResult>) => {
let duration = (systemDateTime.getTime() - startTime).toString()
Log.info(`${method}: Success. duration=${duration} url:${response.config.baseURL}${response.config.url}\n
config=${JSON.stringify(response.config)}\n
status=${response.status}\n
headers${JSON.stringify(response.headers)}\n
body=${response.config.data}\n
params=${JSON.stringify(response.config.params)}\n
data=${JSON.stringify(response.data)}`);
if (isSuccess(response)) {
if (isResultSuccess(response.data)) {
resolve(response.data.data);
} else {
const e: Error = { name: `${response.data.errorCode}`, message: `${response.data.description}` }
reject(e);
}
} else {
const e: Error = { name: `${response.status}`, message: `${response.statusText}` }
reject(e);
}
})
.catch((reason: AxiosError) => {
Log.error(JSON.stringify(reason));
reject(reason)
})
});
}
function isSuccess(response: AxiosResponse): boolean {
return response.status >= 200 && response.status < 300
}
function isResultSuccess(result: ResponseResult): boolean {
return result.result == "SUCCESS"
}
StringBuilder
/**
* @Author wdq
*/
export class StringBuilder {
private value: string[];
constructor() {
this.value = [];
}
append(str: string | number | undefined | null): StringBuilder {
this.value.push(String(str));
return this;
}
appendNotNull(str: string | number | undefined | null): StringBuilder {
if (str != null) {
this.value.push(String(str));
}
return this;
}
build(separator?: string): string {
return this.value.join(separator);
}
}
ResponseResult
export default class ResponseResult {
/**
* Code returned by the network request: success, fail.
*/
errorCode: number | string | undefined | null;
description: string | Resource | undefined | null;
result: string ;
/**
* Data returned by the network request.
*/
data: string | Object | ArrayBuffer | undefined | null;
constructor() {
this.errorCode = "0000";
this.result = '';
this.data = null;
}
}
三、使用
1.在EntryAbility的onWindowStageCreate()中进行初始化
httpDefaultSetting()
2.get请求
/**
* 获取Banner列表
*/
static getBannerList() {
return httpGet<BannerListModel>("banner/get",)
}
3.post请求
static getBannerList() {
return httpPost<BannerListModel>("banner/post",)
}```