ToB企服应用市场:ToB评测及商务社交产业平台
标题:
基于@ohos/axios学习HarmonyOS Next的网络数据哀求
[打印本页]
作者:
九天猎人
时间:
2025-1-3 00:13
标题:
基于@ohos/axios学习HarmonyOS Next的网络数据哀求
基于@ohos/axios学习HarmonyOS Next的网络数据哀求
前言
在 HarmonyOS Next 应用开发中,网络哀求是一个非常重要的功能。本文将通过分析 @ohos/axios 的实现,深入相识 HarmonyOS Next 的网络数据哀求机制。
一、基础知识
1.1 @ohos/axios 简介
@ohos/axios 是 Axios 在 HarmonyOS 平台的适配版本。Axios 是一个基于 Promise 的 HTTP 客户端,可以在浏览器和 Node.js 环境中利用。@ohos/axios 保留了 Axios 的主要特性,同时适配了 HarmonyOS 的网络 API。
1.2 安装与配置
登录后复制
ohpm install @ohos/axios
复制代码
1.
在下令行中利用 ohpm install @ohos/axios 下令安装 @ohos/axios 模块。
需要在 module.json5 中配置权限:
登录后复制
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
剖析:
module.json5 是 HarmonyOS 应用的配置文件。
requestPermissions 用于声明应用需要的权限,这里声明白 ohos.permission.INTERNET 权限,允许应用访问互联网。
二、基本利用
2.1 创建实例
登录后复制
import axios from '@ohos/axios';
// 创建实例
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: {'X-Custom-Header': 'custom-value'}
});
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
剖析:
axios.create 方法创建一个新的 Axios 实例。
baseURL 设置全部哀求的默认基础 URL。
timeout 设置哀求超时时间(毫秒)。
headers 设置默认的哀求头。
2.2 基本哀求示例
登录后复制
// GET 请求
async function getData() {
try {
const response = await axios.get('/user/123');
console.info('Response:', response.data);
} catch (error) {
console.error('Error:', error);
}
}
// POST 请求
async function postData() {
try {
const response = await axios.post('/user', {
name: 'John',
age: 30
});
console.info('Response:', response.data);
} catch (error) {
console.error('Error:', error);
}
}
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
剖析:
axios.get 方法发起一个 GET 哀求,返回一个 Promise 对象。
response.data 包罗服务器返回的数据。
axios.post 方法发起一个 POST 哀求,第二个参数是哀求体数据。
利用 try...catch 语句处理处罚哀求中的异步错误。
三、深入实现原理
3.1 HTTP 哀求适配器
3.1.1 基础 HTTP 哀求适配器
登录后复制
// library/src/main/ets/components/lib/adapters/ohos/http.js
import http from '@ohos.net.http';
export default function httpAdapter(config) {
return new Promise((resolve, reject) => {
let httpRequest = http.createHttp();
// 构建请求配置
const requestConfig = {
method: config.method.toUpperCase(),
header: config.headers,
readTimeout: config.timeout,
connectTimeout: config.timeout,
extraData: config.data ? JSON.stringify(config.data) : undefined
};
// 发起请求
httpRequest.request(
config.url,
requestConfig,
(err, data) => {
if (!err) {
resolve({
data: data.result,
status: data.responseCode,
headers: data.header,
config: config
});
} else {
reject(new AxiosError(
'Request failed',
'ECONNABORTED',
config,
httpRequest,
err
));
}
}
);
});
}
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
剖析:
httpAdapter 函数是一个适配器,用于处理处罚 HTTP 哀求。
http.createHttp() 创建一个 HTTP 哀求对象。
requestConfig 是构建的哀求配置对象,包罗哀求方法、哀求头、超时时间、哀求体数据等。
httpRequest.request 方法发起 HTTP 哀求,传入 URL、哀求配置和回调函数。
回调函数中,假如没有错误,剖析服务器返回的数据并 resolve Promise。
假如有错误,创建一个新的 AxiosError 对象并 reject Promise。
3.1.2 文件下载适配器
登录后复制
// library/src/main/ets/components/lib/adapters/ohos/download.js
import request from '@ohos.request';
export default function downloadAdapter(config) {
return new Promise((resolve, reject) => {
const downloadConfig = {
url: config.url,
header: config.headers,
filePath: config.filePath
};
request.downloadFile(context, downloadConfig)
.then((downloadTask) => {
// 监听下载进度
downloadTask.on('progress', (receivedSize, totalSize) => {
if (config.onDownloadProgress) {
config.onDownloadProgress({
loaded: receivedSize,
total: totalSize
});
}
});
// 监听下载完成
downloadTask.on('complete', (uri) => {
resolve({
data: uri,
status: 200,
config: config
});
});
})
.catch(error => {
reject(new AxiosError(
'Download failed',
'DOWNLOAD_ERROR',
config,
null,
error
));
});
});
}
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
剖析:
downloadAdapter 函数用于处理处罚文件下载哀求。
downloadConfig 是构建的下载配置对象,包罗文件的 URL、哀求头和文件保存路径。
request.downloadFile 方法发起文件下载哀求,返回一个 downloadTask 对象。
downloadTask.on('progress') 监听下载进度,调用 config.onDownloadProgress 回调函数。
downloadTask.on('complete') 监听下载完成,剖析下载结果并 resolve Promise。
假如下载过程中出现错误,创建一个新的 AxiosError 对象并 reject Promise。
3.1.3 文件上传适配器
登录后复制
// library/src/main/ets/components/lib/adapters/ohos/upload.js
import request from '@ohos.request';
export default function uploadAdapter(config) {
return new Promise((resolve, reject) => {
const uploadConfig = {
url: config.url,
header: config.headers,
method: config.method,
files: [],
data: []
};
// 处理 FormData
if (config.data instanceof FormData) {
config.data.forEach((value, key) => {
if (value instanceof File) {
uploadConfig.files.push({
filename: value.name,
name: key,
uri: value.uri,
type: value.type
});
} else {
uploadConfig.data.push({
name: key,
value: value
});
}
});
}
request.uploadFile(context, uploadConfig)
.then((uploadTask) => {
// 监听上传进度
uploadTask.on('progress', (uploadedSize, totalSize) => {
if (config.onUploadProgress) {
config.onUploadProgress({
loaded: uploadedSize,
total: totalSize
});
}
});
// 监听上传完成
uploadTask.on('complete', (response) => {
resolve({
data: response,
status: 200,
config: config
});
});
})
.catch(error => {
reject(new AxiosError(
'Upload failed',
'UPLOAD_ERROR',
config,
null,
error
));
});
});
}
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
剖析:
uploadAdapter 函数用于处理处罚文件上传哀求。
uploadConfig 是构建的上传配置对象,包罗文件的 URL、哀求头、哀求方法、文件列表和普通数据列表。
config.data 假如是 FormData 类型,会遍历并分别处理处罚文件和普通数据。
request.uploadFile 方法发起文件上传哀求,返回一个 uploadTask 对象。
uploadTask.on('progress') 监听上传进度,调用 config.onUploadProgress 回调函数。
uploadTask.on('complete') 监听上传完成,剖析上传结果并 resolve Promise。
假如上传过程中出现错误,创建一个新的 AxiosError 对象并 reject Promise。
3.2 拦截器实现
登录后复制
// 请求拦截器
axios.interceptors.request.use(
config => {
// 在发送请求之前做些什么
config.headers['Authorization'] = `Bearer ${getToken()}`;
return config;
},
error => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 响应拦截器
axios.interceptors.response.use(
response => {
// 对响应数据做点什么
return response.data;
},
error => {
// 对响应错误做点什么
if (error.response.status === 401) {
// 处理认证错误
}
return Promise.reject(error);
}
);
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
剖析:
axios.interceptors.request.use 方法注册哀求拦截器。
哀求拦截器的第一个参数是在发送哀求之前对哀求配置进行处理处罚的函数,可以添加或修改哀求头等。
哀求拦截器的第二个参数是在哀求错误时处理处罚错误的函数。
axios.interceptors.response.use 方法注册相应拦截器。
相应拦截器的第一个参数是在收到相应后对相应数据进行处理处罚的函数。
相应拦截器的第二个参数是在相应错误时处理处罚错误的函数,可以根据差别的错误状态码进行差别的处理处罚。
四、高级特性
4.1 并发哀求
登录后复制
async function makeMultipleRequests() {
try {
const [users, posts] = await Promise.all([
axios.get('/users'),
axios.get('/posts')
]);
console.info('Users:', users.data);
console.info('Posts:', posts.data);
} catch (error) {
console.error('Error:', error);
}
}
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
剖析:
Promise.all 方法用于并发执行多个哀求,并等待全部哀求完成。
axios.get('/users') 和 axios.get('/posts') 分别发起两个 GET 哀求。
两个哀求的结果将被解构赋值给 users 和 posts。
利用 try...catch 语句处理处罚并发哀求中的异步错误。
4.2 哀求配置
登录后复制
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: {
'Content-Type': 'application/json'
},
// 自定义转换数据
transformRequest: [(data) => {
// 对发送的数据进行转换
return JSON.stringify(data);
}],
transformResponse: [(data) => {
// 对接收的数据进行转换
return JSON.parse(data);
}]
});
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
剖析:
axios.create 方法创建一个新的 Axios 实例。
transformRequest 是一个数组,包罗一个或多个函数,这些函数在哀求发送之前对哀求体数据进行处理处罚。
transformResponse 是一个数组,包罗一个或多个函数,这些函数在相应数据接收之后对数据进行处理处罚。
JSON.stringify(data) 将数据转换为 JSON 字符串。
JSON.parse(data) 将 JSON 字符串转换为 JavaScript 对象。
4.3 错误处理处罚
登录后复制
async function handleRequestWithError() {
try {
await axios.get('/api/data');
} catch (error) {
if (error.response) {
// 服务器返回错误状态码
console.error('Status:', error.response.status);
console.error('Data:', error.response.data);
} else if (error.request) {
// 请求已发送但没有收到响应
console.error('No response:', error.request);
} else {
// 请求配置出错
console.error('Error:', error.message);
}
}
}
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
剖析:
try...catch 语句用于捕捉哀求中的异步错误。
error.response 对象包罗服务器返回的错误信息,包罗状态码和数据。
error.request 对象包罗已发送的哀求信息,但没有收到相应。
error.message 包罗哀求配置出错的信息。
五、最佳实践
5.1 封装 API 服务
登录后复制
// api/index.ets
import axios from '@ohos/axios';
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000
});
export const userService = {
getUser: (id: string) => api.get(`/users/${id}`),
createUser: (userData: any) => api.post('/users', userData),
updateUser: (id: string, userData: any) => api.put(`/users/${id}`, userData),
deleteUser: (id: string) => api.delete(`/users/${id}`)
};
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
剖析:
api 是一个 Axios 实例,设置了基础 URL 和超时时间。
userService 是一个对象,封装了用户相关的 API 哀求方法。
每个方法都利用 api 实例发起哀求,传入差别的参数。
5.2 统一错误处理处罚
在 API 哀求中,统一错误处理处罚是非常重要的,它可以资助我们更好地管理和相应应用步伐中的非常。通过利用 axios 的拦截器功能,我们可以会合地处理处罚全部的哀求和相应错误,从而简化代码逻辑,进步代码的可维护性。
5.2.1 错误拦截器的实现
在 setupErrorHandler 函数中,我们定义了一个相应拦截器,该拦截器会检查每个相应的状态码,并根据状态码执行相应的错误处理处罚逻辑。
登录后复制
// utils/errorHandler.ets
import axios from '@ohos/axios';
export function setupErrorHandler(axiosInstance) {
axiosInstance.interceptors.response.use(
(response) => {
// 如果请求成功,直接返回响应数据
return response;
},
(error) => {
// 如果请求失败,处理错误
if (error.response) {
// 服务器返回了错误状态码
switch (error.response.status) {
case 401:
// 处理未授权错误
console.error('未授权访问,请重新登录');
// 例如,可以重定向到登录页面
// navigateToLogin();
break;
case 403:
// 处理禁止访问错误
console.error('禁止访问该资源');
// 可以显示一个禁止访问的提示
// showAlert('禁止访问该资源');
break;
case 404:
// 处理资源未找到错误
console.error('请求的资源未找到');
// 可以显示一个资源未找到的提示
// showAlert('请求的资源未找到');
break;
case 500:
// 处理服务器内部错误
console.error('服务器内部错误');
// 可以显示一个服务器错误的提示
// showAlert('服务器内部错误');
break;
default:
// 处理其他状态码的错误
console.error('未知错误:', error.response.status, error.response.data);
// 可以显示一个通用的错误提示
// showAlert('未知错误');
break;
}
} else if (error.request) {
// 请求已发送但没有收到响应
console.error('请求超时或网络问题');
// 可以显示一个请求超时或网络问题的提示
// showAlert('请求超时或网络问题');
} else {
// 请求配置出错
console.error('请求配置错误:', error.message);
// 可以显示一个请求配置错误的提示
// showAlert('请求配置错误');
}
// 继续向下抛出错误,以便上层代码可以处理
return Promise.reject(error);
}
);
}
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
5.2.2 利用错误拦截器
在创建 axios 实例时,我们可以调用 setupErrorHandler 函数来设置错误拦截器。
登录后复制
// api/index.ets
import axios from '@ohos/axios';
import { setupErrorHandler } from './utils/errorHandler';
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000
});
// 设置错误拦截器
setupErrorHandler(api);
export const userService = {
getUser: (id: string) => api.get(`/users/${id}`),
createUser: (userData: any) => api.post('/users', userData),
updateUser: (id: string, userData: any) => api.put(`/users/${id}`, userData),
deleteUser: (id: string) => api.delete(`/users/${id}`)
};
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
5.2.2.1 axios.create 的配置
登录后复制
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000
});
复制代码
1.
2.
3.
4.
baseURL: 设置基础 URL,全部哀求都会在这个基础 URL 上进行拼接。
timeout: 设置哀求的超时时间,单位是毫秒。假如哀求高出这个时间还没有相应,哀求会被取消。
5.2.2.2 设置错误拦截器
登录后复制
setupErrorHandler(api);
复制代码
1.
这行代码调用了 setupErrorHandler 函数,并将 axios 实例 api 作为参数传递。setupErrorHandler 函数会在 api 实例上添加一个相应拦截器。
5.2.2.3 相应拦截器的逻辑
登录后复制
axiosInstance.interceptors.response.use(
(response) => {
// 如果请求成功,直接返回响应数据
return response;
},
(error) => {
// 如果请求失败,处理错误
if (error.response) {
// 服务器返回了错误状态码
switch (error.response.status) {
case 401:
// 处理未授权错误
console.error('未授权访问,请重新登录');
// 例如,可以重定向到登录页面
// navigateToLogin();
break;
case 403:
// 处理禁止访问错误
console.error('禁止访问该资源');
// 可以显示一个禁止访问的提示
// showAlert('禁止访问该资源');
break;
case 404:
// 处理资源未找到错误
console.error('请求的资源未找到');
// 可以显示一个资源未找到的提示
// showAlert('请求的资源未找到');
break;
case 500:
// 处理服务器内部错误
console.error('服务器内部错误');
// 可以显示一个服务器错误的提示
// showAlert('服务器内部错误');
break;
default:
// 处理其他状态码的错误
console.error('未知错误:', error.response.status, error.response.data);
// 可以显示一个通用的错误提示
// showAlert('未知错误');
break;
}
} else if (error.request) {
// 请求已发送但没有收到响应
console.error('请求超时或网络问题');
// 可以显示一个请求超时或网络问题的提示
// showAlert('请求超时或网络问题');
} else {
// 请求配置出错
console.error('请求配置错误:', error.message);
// 可以显示一个请求配置错误的提示
// showAlert('请求配置错误');
}
// 继续向下抛出错误,以便上层代码可以处理
return Promise.reject(error);
}
);
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
response:乐成相应时的处理处罚函数。假如哀求乐成,直接返回相应数据。
error:失败相应时的处理处罚函数。根据 error 的差别属性,我们可以区分差别类型的错误:
error.response:服务器返回了错误状态码。我们可以利用 switch 语句来处理处罚差别状态码的错误,并执行相应的逻辑。
error.request:哀求已发送但没有收到相应。这种环境通常是由于网络问题或哀求超时引起的。
error.message:哀求配置出错。比方,URL 天生错误或哀求头配置错误。
5.2.3 重试机制
在实际应用中,我们可能希望在某些环境下自动重试哀求,比方网络不稳固时。我们可以通过扩展错误拦截器来实现这一功能。
登录后复制
// utils/errorHandler.ets
export function setupErrorHandler(axiosInstance) {
let retryCount = 0;
const maxRetries = 3;
axiosInstance.interceptors.response.use(
(response) => {
return response;
},
(error) => {
const originalRequest = error.config;
if (error.response) {
switch (error.response.status) {
case 401:
console.error('未授权访问,请重新登录');
// 例如,可以重定向到登录页面
// navigateToLogin();
break;
case 403:
console.error('禁止访问该资源');
// 可以显示一个禁止访问的提示
// showAlert('禁止访问该资源');
break;
case 404:
console.error('请求的资源未找到');
// 可以显示一个资源未找到的提示
// showAlert('请求的资源未找到');
break;
case 500:
console.error('服务器内部错误');
// 可以显示一个服务器错误的提示
// showAlert('服务器内部错误');
break;
default:
console.error('未知错误:', error.response.status, error.response.data);
// 可以显示一个通用的错误提示
// showAlert('未知错误');
break;
}
} else if (error.request) {
console.error('请求超时或网络问题');
// 可以显示一个请求超时或网络问题的提示
// showAlert('请求超时或网络问题');
// 重试机制
if (retryCount < maxRetries) {
retryCount++;
return axiosInstance(originalRequest);
}
} else {
console.error('请求配置错误:', error.message);
// 可以显示一个请求配置错误的提示
// showAlert('请求配置错误');
}
// 继续向下抛出错误,以便上层代码可以处理
return Promise.reject(error);
}
);
// 重置重试计数器
axiosInstance.interceptors.request.use(
(config) => {
retryCount = 0;
return config;
},
(error) => {
return Promise.reject(error);
}
);
}
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
retryCount:记录当前哀求的重试次数。
maxRetries:设置最大重试次数。
在 error.request 分支中,我们检查 retryCount 是否小于 maxRetries,假如小于,则递增 retryCount 并重新发起哀求。
在 axiosInstance.interceptors.request.use 中,我们重置 retryCount,以确保每次新的哀求时计数器从 0 开始。
5.2.4 自定义错误处理处罚
在某些环境下,我们可能希望为差别的 API 提供差别的错误处理处罚逻辑。我们可以通过在服务层定义自定义的错误处理处罚函数来实现这一点。
登录后复制
// api/index.etsimport axios from '@ohos/axios';import { setupErrorHandler } from './utils/errorHandler';const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000
});// 设置默认错误拦截器setupErrorHandler(api);// 自定义错误处理处罚api.interceptors.response.use( (response) => { return response; }, (error) => { if (error.config && error.config.customErrorHandling) { // 调用自定义错误处理处罚函数 error.config.customErrorHandling(error); } return Promise.reject(error); });export const userService = { getUser: (id: string) => api.get(`/users/${id}`, { customErrorHandling: (error) => { console.error('自定义错误处理处罚:', error); // 可以在这里添加自定义的错误处理处罚逻辑 } }), createUser: (userData: any) => api.post('/users', userData), updateUser: (id: string, userData: any) => api.put(`/users/${id}`, userData), deleteUser: (id: string) => api.delete(`/users/${id}`)};
复制代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
在 api.interceptors.response.use 中,我们检查 error.config 是否包罗 customErrorHandling 属性。
假如存在 customErrorHandling 属性,我们调用该函数并传递错误对象。
在 userService 中,我们在每个哀求的配置对象中添加 customErrorHandling 属性,以便为每个哀求提供差别的错误处理处罚逻辑。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4