《鸿蒙PC Electron 网络请求实战:HTTP/HTTPS 调用、跨域解决、异常处理》
<canvas_command><action>create</action><identifier>hongmeng-electron-network-request-guide</identifier>
<title>鸿蒙 Electron 网络请求实战:HTTP/HTTPS 调用、跨域解决、异常处理</title><genre>实战教程</genre><type>type/ddxml</type><content><title id="0">鸿蒙 Electron 网络请求实战:HTTP/HTTPS 调用、跨域解决、异常处理</title><p id="1">鸿蒙 Electron 应用开发中,网络请求是对接后端服务、实现数据交互的核心能力。与传统 Web 应用相比,鸿蒙 Electron 因“主进程+渲染进程”的架构特性,在网络请求时需处理权限配置、跨域限制、系统拦截等特殊问题。本文聚焦生产级开发场景,从基础配置到架构设计,再到异常处理,逐步拆解 HTTP/HTTPS 调用、跨域解决方案、断网处理、超时重试等核心需求,提供高质量、可直接复用的代码案例,帮助开发者快速搭建健壮的网络请求体系。</p>
<callout id="2" emoji="⚠️">
核心认知:① 鸿蒙系统对网络请求有严格权限管控,未声明权限会直接拦截请求;② 渲染进程请求受浏览器跨域规则限制,主进程请求无跨域问题;③ 网络请求需兼顾鸿蒙设备兼容性与Electron架构特性,推荐"主进程代理"方案。
</callout>
<h1 id="3">一、基础准备:鸿蒙网络权限配置与依赖安装</h1>
<p id="4">网络请求前需完成两项基础操作:声明鸿蒙系统网络权限(避免请求被拦截)、安装网络请求依赖(选用axios作为核心库)。</p>
<h2 id="5">1.1 鸿蒙网络权限配置(config.json)</h2>
<p id="6">在项目根目录的 <code id="7">config.json 中声明网络权限、域名白名单,允许HTTP/HTTPS请求:
{
"app": {
"bundleName": "com.example.networkdemo",
"version": { "code": 1000000, "name": "1.0.0" }
},
"module": {
"name": "entry",
"mainAbility": "MainAbility",
"deviceType": ["phone", "pc", "tv"],
// 1. 声明网络权限
"reqPermissions": [{
"name": "ohos.permission.INTERNET", // 核心网络权限
"reason": "访问后端API服务,实现数据交互", // 权限申请理由(用户可见)
"usedScene": {
"ability": ["com.example.networkdemo.MainAbility"],
"when": "always" // 始终需要该权限
}
}],
// 2. 网络请求配置(域名白名单+明文请求控制)
"network": {
"cleartextTraffic": true, // 开发环境允许HTTP明文请求(生产环境建议关闭)
"domainSettings": {
"domains": [
{ "domain": "api.example.com", "type": "normal" }, // 后端API域名(必配)
{ "domain": "*.example.com", "type": "normal" }, // 通配符支持(子域名)
{ "domain": "api.github.com", "type": "normal" } // 第三方API域名
]
}
}
}
}
关键说明:① ohos.permission.INTERNET 是网络请求的核心权限,缺失会导致所有请求失败;② 域名白名单需填写实际对接的后端域名;③ 生产环境应将 cleartextTraffic 设为 false,仅允许HTTPS请求。
plaintext
<h2 id="14">1.2 依赖安装(axios)</h2>
<p id="15">axios 是前端生态中最成熟的网络请求库,支持拦截器、超时控制、取消请求等核心功能,鸿蒙 Electron 中可直接安装使用:</p>
<pre id="16"><code id="17" lang="bash"># 进入项目根目录
cd your-project-name
安装 axios(推荐使用稳定可靠的 1.x 版本) npm install axios@1.6.8 --save
为 TypeScript 项目安装类型声明文件(必需) npm install @types/axios --save-dev
二、架构设计:生产级网络请求体系(主进程代理方案)
推荐采用"渲染进程调用 → IPC通信 → 主进程代理请求"的分层架构,具有以下核心优势:
- 规避渲染进程跨域问题
- 统一权限控制与异常处理
- 便于扩展请求监控、加密等功能
整体架构流程: 渲染进程API封装 → 预加载脚本暴露接口 → 主进程IPC监听 → 主进程网络请求核心 → 后端服务
2.1 主进程:网络请求核心封装(含拦截器、异常处理)
在主进程中创建网络请求服务,集成以下核心能力:
- 请求/响应拦截器
- 超时重试机制
- 断网检测功能
// src/main/services/networkService.ts
import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
import { app } from '@hmos/electron';
import { networkInterfaces } from 'os';
import path from 'path';
import fs from 'fs/promises';
// 1. 创建axios实例(主进程无跨域限制)
const apiClient = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
headers: {
'Content-Type': 'application/json;charset=utf-8',
'User-Agent': `HarmonyElectron/${app.getVersion()}-${process.platform}`
}
});
// 2. 请求拦截器:统一添加请求头、认证信息
apiClient.interceptors.request.use(async (config: AxiosRequestConfig) => {
// 自动添加认证Token
const tokenPath = path.join(app.getPath('userData'), 'auth-token.json');
try {
const tokenContent = await fs.readFile(tokenPath, 'utf8');
const { token } = JSON.parse(tokenContent);
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
} catch (error) {
console.log('未找到认证Token,继续无认证请求');
}
// 添加请求ID
config.headers['X-Request-Id'] = Date.now() + '-' + Math.random().toString(36).substr(2, 9);
return config;
}, (error: AxiosError) => {
console.error('请求参数异常:', error.config?.data, error.message);
return Promise.reject({ code: 'REQUEST_PARAM_ERROR', message: error.message });
});
// 3. 响应拦截器:统一异常处理、数据格式化
apiClient.interceptors.response.use((response: AxiosResponse) => {
const { data } = response;
if (data.code !== 0) {
return Promise.reject({
code: data.code,
message: data.message || '业务处理失败',
rawData: data
});
}
return data.data;
}, (error: AxiosError) => {
const { config, response, request } = error;
// 4. 断网检测
if (!checkNetworkStatus()) {
return Promise.reject({ code: 'NETWORK_DISCONNECTED', message: '网络连接已断开,请检查网络设置' });
}
// 5. 超时重试机制
if (error.code === 'ECONNABORTED' && config?.['retryCount'] < 3) {
const retryCount = (config?.['retryCount'] || 0) + 1;
const retryDelay = retryCount * 1000;
console.log(`请求超时,正在进行第${retryCount}次重试(延迟${retryDelay}ms)`, config.url);
return new Promise((resolve) => {
setTimeout(() => {
resolve(apiClient({ ...config, retryCount }));
}, retryDelay);
});
}
// 6. HTTP状态码错误处理
const status = response?.status;
let errorMsg = '网络请求失败';
switch (status) {
case 401:
errorMsg = '登录已过期,请重新登录';
break;
case 403:
errorMsg = '权限不足,无法访问该资源';
break;
case 404:
errorMsg = '请求的资源不存在';
break;
case 500:
case 502:
case 503:
errorMsg = '服务器内部错误,请稍后重试';
break;
default:
errorMsg = error.message || '未知网络错误';
}
// 7. 记录错误日志
console.error(`[NETWORK_ERROR] ${config?.method?.toUpperCase()} ${config?.url} | 状态码: ${status} | 错误: ${errorMsg}`, error.stack);
return Promise.reject({ code: status });
## 2.2 主进程:IPC 通信监听(对接渲染进程)
主进程通过 IPC 监听渲染进程的请求,调用网络请求服务并将结果返回给渲染进程:
```typescript
// src/main/ipc/networkIpc.ts
import { ipcMain } from '@hmos/electron';
import { http, checkNetworkStatus } from '../services/networkService';
// 注册网络相关 IPC 处理器(统一管理)
export const registerNetworkIpcHandlers = () => {
// 1. 通用网络请求接口(支持所有 HTTP 方法)
ipcMain.handle('network-request', async (_, options) => {
try {
const { method = 'GET', url, params, data, config } = options;
let result;
// 根据请求方法调用对应 http 函数
switch (method.toUpperCase()) {
case 'GET':
result = await http.get(url, params, config);
break;
case 'POST':
result = await http.post(url, data, config);
break;
case 'PUT':
result = await http.put(url, data, config);
break;
case 'DELETE':
result = await http.delete(url, params, config);
break;
default:
throw new Error(`不支持的请求方法: ${method}`);
}
// 成功响应格式
return { success: true, data: result };
} catch (error) {
// 失败响应格式(与渲染进程约定)
return {
success: false,
error: {
code: error.code || 'UNKNOWN_ERROR',
message: error.message || '网络请求失败'
}
};
}
});
// 2. 网络状态检测接口(单独暴露,便于渲染进程预检测)
ipcMain.handle('check-network-status', async () => {
return { online: checkNetworkStatus(), timestamp: Date.now() };
});
};
2.3 预加载脚本:暴露安全通信接口(preload.js)
预加载脚本运行在渲染进程上下文与主进程上下文之间,通过 contextBridge 向渲染进程暴露安全的 IPC 通信接口,避免渲染进程直接访问敏感 API:
// src/common/preload.js
import { contextBridge, ipcRenderer } from '@hmos/electron';
// 向渲染进程暴露网络请求相关接口(白名单机制)
contextBridge.exposeInMainWorld('networkApi', {
// 通用网络请求
request: (options) => ipcRenderer.invoke('network-request', options),
// 网络状态检测
checkStatus: () => ipcRenderer.invoke('check-network-status')
});
// TypeScript 类型声明(可选,提升开发体验)
declare global {
interface Window {
networkApi: {
request: (options: {
method?: string;
url: string;
params?: any;
data?: any;
config?: any;
}) => Promise<{
success: boolean;
data?: any;
error?: { code: string | number; message: string };
}>;
checkStatus: () => Promise<{ online: boolean; timestamp: number }>;
};
}
}
2.4 渲染进程:API 封装(业务层调用)
在渲染进程中封装业务 API,统一调用预加载脚本暴露的接口,避免重复代码,提升可维护性:
// src/renderer/services/api.ts
import { Ref } from 'vue';
// 1. 类型定义(TypeScript 项目必配,确保类型安全)
// 响应结果类型(与主进程约定)
interface ApiResponse<T> {
success: boolean;
data?: T;
error?: { code: string | number; message: string };
}
// 业务数据类型示例
export interface UserInfo {
id: string;
name: string;
email: string;
avatar: string;
createTime: string;
}
export interface PageResult
欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/
更多推荐



所有评论(0)