Node.js使用node-fetch读取本地JSON报ERR_INVALID_URL错误如何解决?
报错原因
Node环境下的fetch(包括你安装的node-fetch@3依赖)不支持直接传入相对路径读取本地文件,它仅支持http/https/file协议的合法URL,你传入./json/data.json相对路径无法被解析为合法URL,因此抛出ERR_INVALID_URL错误。
解决方案
方案1(推荐):使用原生fs模块读取本地JSON
读取本地文件无需额外引入fetch相关依赖,直接用Node内置的fs模块即可,ES模块(.mjs)环境下适配代码如下:
- 先导入依赖:
import { readFile } from 'node:fs/promises'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path';
- 替换原有fetch读取JSON的代码:
// 构造当前文件所在目录路径,适配ES模块无__dirname的问题 const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // 读取并解析JSON const info = JSON.parse(await readFile(join(__dirname, './json/data.json'), 'utf8'));
方案2:仍使用fetch的适配方案
如果要继续用fetch读取本地文件,需要把相对路径转为合法的file协议URL:
const jsonFileUrl = new URL('./json/data.json', import.meta.url); const info = await fetch(jsonFileUrl).then(res => res.json());
额外问题修正
你现有代码中循环内的天气接口请求是异步操作,循环结束后直接打印lstValid时,异步请求还未完成,会出现打印空数组的问题,可通过Promise.all等待所有请求完成后再操作,修正后的完整函数示例:
async function calcWeather() { // 构造目录路径、读取本地JSON const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const info = JSON.parse(await readFile(join(__dirname, './json/data.json'), 'utf8')); console.log(info); // 收集所有天气接口请求的Promise const requestTasks = info.map(async (item) => { const baseInfo = item[0]; const base = `https://api.openweathermap.org/data/2.5/weather?lat=${baseInfo.latjson}&lon=${baseInfo.lonjson}&appid=${api_key}&units=metric&lang=sp`; const res = await fetch(base); const weatherData = await res.json(); const myObject = { Id_Oficina: baseInfo.IdOficina, Humedad: weatherData.main.humidity, Nubes: weatherData.clouds.all, Sensacion: weatherData.main.feels_like, Temperatura: weatherData.main.temp, Descripcion: weatherData.weather[0].description, }; return myObject.Temperatura < 99 ? myObject : null; }); // 等待所有请求完成,过滤无效值得到最终有效数组 const lstValid = (await Promise.all(requestTasks)).filter(Boolean); console.log(lstValid); // 此处可执行后续存入数据库的操作 }
内容的提问来源于stack exchange,提问作者Martín JF
相关产品推荐
相关产品推荐

