Electron主进程Axios不支持URL对象,渲染进程为何正常?
Electron主进程中Axios调用URL对象报错的原因与解决方法
问题场景
我有一个基于Electron的React应用,渲染进程里一直用如下方式调用Axios,完全正常:
import React from 'react'; import axios from 'axios'; import { useQuery } from 'react-query'; // ... const { data: queryResponse, isLoading } = useQuery( [query, getParameters], () => { const url = new URL(`https://www.devel.server/${query}`); url.search = new URLSearchParams(getParameters); return axios.get(url); } );
但把相同逻辑搬到主进程时,调用axios.get()直接抛出异常:
const { app, BrowserWindow, Menu, ipcMain } = require('electron'); const { odtParse } = require('./main/odt-parser.js'); const shell = require('electron').shell; const path = require('path'); import axios from 'axios'; ipcMain.on('generate-employee-contract', (event, employeeId) => { const url = new URL('https://www.devel.server/employee-contract-summary'); url.search = new URLSearchParams({ employeeId }); axios.get(url).then(function (response) { const filename = odtParse('./assets/Contract.odt', response.variables, response.conditions); shell.openPath(path.join(__dirname, filename)); }) });
报错信息:
UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]:
The "url" argument must be of type string. Received an instance of URL
补充:console.log(url)输出确认是合法的URL对象:
URL { href: 'https://www.devel.server/employee-contract-summary?employeeId=377', origin: 'https://www.devel.server', protocol: 'https:', username: '', password: '', host: 'www.devel.server', hostname: 'www.devel.server', port: '', pathname: '/employee-contract-summary', search: '?employeeId=377', searchParams: URLSearchParams { 'employeeId' => '377' }, hash: '' }
原因分析
核心差异在于Electron的渲染进程和主进程的运行环境不同:
- 渲染进程是浏览器环境,Axios使用XMLHttpRequest适配器,它会自动将URL对象隐式转换为字符串(调用
URL.toString(),等价于取href属性)。 - 主进程是Node.js环境,Axios使用Node.js的http/https适配器,该适配器不支持直接传入URL对象作为第一个参数,要求必须是字符串类型的URL,或者包含
url字段的配置对象。
两个进程用的Axios可能是同一个版本,但因为运行环境的适配器不同,导致对参数的处理逻辑不一样。
解决方法
方法1:将URL对象转为字符串
直接传入url.href或者url.toString()即可,这两个都会返回完整的带查询参数的URL字符串:
ipcMain.on('generate-employee-contract', (event, employeeId) => { const url = new URL('https://www.devel.server/employee-contract-summary'); url.search = new URLSearchParams({ employeeId }); // 用url.href或url.toString()转为字符串 axios.get(url.href).then(function (response) { const filename = odtParse('./assets/Contract.odt', response.variables, response.conditions); shell.openPath(path.join(__dirname, filename)); }) });
方法2:使用Axios配置对象拆分URL属性
如果需要更灵活的配置,可以把URL对象的属性拆到Axios的配置对象中:
ipcMain.on('generate-employee-contract', (event, employeeId) => { const url = new URL('https://www.devel.server/employee-contract-summary'); url.search = new URLSearchParams({ employeeId }); axios.get({ baseURL: url.origin, url: url.pathname, params: url.searchParams }).then(function (response) { const filename = odtParse('./assets/Contract.odt', response.variables, response.conditions); shell.openPath(path.join(__dirname, filename)); }) });
内容的提问来源于stack exchange,提问作者Primordial_Hamster
相关产品推荐
相关产品推荐

