在进行网络请求的封装之前,先来分析一下我们项目所用到的接口的基本情况: 1. 在请求的接口中添加了签名。
2.在非登录接口中添加了token。 基于以上基本的情况。我们开始来对Axios做封装。
"@ohos/axios": "^2.1.1",
前面我们已经介绍了我们的接口请求中的2个必要因素是签名和token,现在我们开始对这2块的实现开始介绍
签名的生成
我们的签名是将当前所有的请求参数加上当前的时间戳来生成的签名,所以们把请求中的参数做遍历放到一个数组中
在添加一个当前时间戳,以及生成的签名作为新的请求参数
private generateSignature(params: RequestParams): RequestParams {
const time = Date.now().toString().substr(0, 10);
let str = pref + "&";
const allParams: RequestParams = {};
Object.keys(params).forEach((key) => {
allParams[key] = params[key];
});
allParams['timestamp'] = time;
const sortedKeys = Object.keys(allParams).sort();
sortedKeys.forEach((key) => {
const value = allParams[key];
if (typeof value !== 'object' && value !== null) {
if (key === "timestamp") {
str += `${key}=${time}&`;
} else if (key !== "sign") {
str += `${key}=${decodeURIComponent(String(value))}&`;
}
}
});
str += suff;
allParams['sign'] = CryptoJS.MD5(str).toString()
return allParams
}
请求头token
我们在登录接口获取到token后存储到preferences中,然后在再请求头添加类似的代码
headers.set('Authorization', token);
接下来我们创建一个PolarisHttp.ets开始对基本的get ,post ,put,patch等方法的封装
首先我们需要创建一个网络请求对象 PolarisHttpRequest,定义基础的变量
config: HttpRequestConfig; //请求配置参数
interceptorHooks?: InterceptorHooks; //拦截器
instance: AxiosInstance; //阿修罗实例
阿修罗网络请求核心代码:
request<T = CommonType>(config: HttpRequestConfig): Promise<T> {
return new Promise<T>((resolve, reject) => {
this.instance
.request<CommonType, T>(config)
.then(res => {
resolve(res);
})
.catch((err: Error) => {
LogUtils.error("网络请求Request异常:", err.toString());
if (err instanceof AxiosError) {
showToast(err.message)
}
reject(err);
});
});
}
GET 请求封装:
public get<T = CommonType>(config: HttpRequestConfig): Promise<T> {
// 确保 params 存在
if (!config.params) {
config.params = {};
}
const allParams: RequestParams = this.generateSignature(config.params);
// Object.keys(config.params).forEach(key => {
// allParams[key] = config.params[key];
// });
// 创建新的 headers 对象
const headers = new AxiosHeaders(config.headers);
return new Promise<T>((resolve, reject) => {
const getTokenAndSendRequest = () => {
if (!config.isLoginState) {
UserLoginHelper.getUserToken().then(token => {
if (token && typeof token === 'string') {
LogUtils.error('网络请求Request Authorization', token);
headers.set('Authorization', token);
} else {
LogUtils.error('网络请求Request 请求未获取的Token信息');
}
sendRequest();
}).catch(reject);
} else {
sendRequest();
}
};
const sendRequest = () => {
// 构建新的配置对象
const newConfig: HttpRequestConfig = {
method: 'GET',
url: config.url,
params: allParams,
headers: headers,
data: config.data,
timeout: config.timeout,
responseType: config.responseType
};
// 发送请求
this.request<T>(newConfig).then(resolve).catch(reject);
};
getTokenAndSendRequest();
});
}
POST请求封装:
public post<T = CommonType>(config: HttpRequestConfig): Promise<T> {
// 确保 data 存在
if (!config.data) {
config.data = {};
}
let allData: RequestParams = {};
// 复制原有数据
Object.keys(config.data).forEach(key => {
allData[key] = config.data[key];
});
// 使用 generateSignature 方法生成签名
allData = this.generateSignature(allData);
// 创建新的 headers 对象
const headers = new AxiosHeaders(config.headers);
// 使用Promise来处理异步token获取
return new Promise<T>((resolve, reject) => {
const getTokenAndSendRequest = () => {
if (!config.isLoginState) {
LogUtils.error('网络请求Request--Authorization...token..!config.isLoginState');
UserLoginHelper.getUserToken().then(token => {
if (token && typeof token === 'string') {
LogUtils.error('网络请求Request--Authorization', token);
headers.set('Authorization', token);
} else {
LogUtils.error('网络请求Request--Authorization--请求未获取的Token信息');
}
sendRequest();
}).catch(reject);
} else {
LogUtils.error('网络请求Request--Authorization...token..config.isLoginState');
sendRequest();
}
};
const sendRequest = () => {
// 构建新的配置对象
const newConfig: HttpRequestConfig = {
method: 'POST',
url: config.url,
data: allData,
headers: headers,
timeout: config.timeout,
responseType: config.responseType
};
// 发送请求
this.request<T>(newConfig).then(resolve).catch(reject);
};
getTokenAndSendRequest();
});
// // 构建新的配置对象
// const newConfig: HttpRequestConfig = {
// method: 'POST',
// url: config.url,
// data: allData,
// headers: headers,
// timeout: config.timeout,
// responseType: config.responseType
// };
// // 返回请求
// return this.request<T>(newConfig);
}
我们可以看到上述的get 请求和post请求都用了2次回调,因为我们的 preferences数据的获取是一个异步过程(因为js我不是很熟悉如果你有好的实现,也可以分享下) 我们需要先异步获取到token 然后在添加到请求头中当中去.
const httpClient = new PolarisHttpRequest({
baseURL: 'https://api.example.com',
timeout: 5000,
interceptorHooks: {
requestInterceptor: (config) => {
// 请求拦截逻辑
return config;
},
responseInterceptor: (response) => {
// 响应拦截逻辑
return response;
}
}
});
// GET请求示例
httpClient.get<ApiResponse<UserInfo>>({
url: '/user/info',
params: { userId: 123 }
}).then(response => {
console.log(response.data);
}).catch(error => {
console.error(error);
});
// POST请求示例
httpClient.post<ApiResponse<LoginResult>>({
url: '/user/login',
data: { username: 'example', password: 'password' }
}).then(response => {
console.log(response.data);
}).catch(error => {
console.error(error);
});
至此,您可以在ArkTS应用中更加方便地管理和发送HTTP请求,同时保证了请求的安全性和一致性。封装类提供的拦截器和错误处理机制可以大大简化API调用的复杂度。