Node.js环境中怎么使用axios或http模块发送GET请求

作者:夜航船时间:2026-11-03 21:57:15浏览:339

详细讲解在Node.js开发环境中如何分别使用axios第三方库与原生http/https模块发送GET请求,包含完整代码示例、流式接收机制、错误处理及生产选型建议。

运行环境:Node.js >= 14.x 核心协议:HTTP/1.1 & HTTPS 技术主题:网络数据获取与客户端实现
Node.js环境中怎么使用axios或http模块发送GET请求
图 0:Node.js 环境下两种主流 GET 请求发送途径核心能力对比

在 Node.js 服务端应用开发中,向外部第三方 API 或内部微服务发送 HTTP GET 请求获取数据是核心的高频操作。解决这一需求通常有两种路径:一种是安装社区事实标准的第三方库 axios,依靠其内置的 Promise 支持、自动查询参数编码与 JSON 反序列化简化代码;另一种是直接调用 Node.js 内置的核心模块 http(针对 HTTP)或 https(针对 HTTPS),以零依赖、底层流式(Stream)的方式完成请求。两者的代码形态与适用场景存在显著差异,本文将分别给出完整实现步骤、避坑要点与选型建议。

一、使用 axios 发送 GET 请求

axios 是一个基于 Promise 的 HTTP 客户端,在 Node.js 服务端和浏览器端具有高度一致的 API。在服务端环境中,axios 会自动调用 Node.js 底层的 http/https 模块,但在上层为开发者处理了复杂的细节,如 URL 参数拼装、响应体流聚合、JSON 文本反序列化以及 HTTP 状态码校验。

1. 安装与准备工作

在现有的 Node.js 项目根目录下打开终端,通过包管理器安装 axios:

npm install axios

安装完成后即可在 .js 或 .mjs 文件中引入使用。如果项目采用 CommonJS 规范,使用 const axios = require('axios');;如果采用 ES Module,使用 import axios from 'axios';。

2. 基础请求与参数传递

发送 GET 请求时,查询参数(Query Parameters)建议通过配置对象中的 params 属性传递,而不是手动在 URL 末尾用字符串拼接。axios 会自动使用 encodeURIComponent 对键和值进行安全编码,避免中文或特殊字符导致请求格式错误。

Node.js环境中怎么使用axios或http模块发送GET请求
图 1:使用 Axios 发送 GET 请求的执行步骤及状态分流

3. 完整代码示例(包含超时与分层错误处理)

以下代码演示了在 Node.js 中使用 async/await 语法配合 axios 发送带有 Query 参数、自定义 Header 和超时控制的 GET 请求,并对不同的异常情况(服务端返回 4xx/5xx、网络中断、DNS 解析失败等)进行分层捕获:

// axios_get_demo.js
const axios = require('axios');

async function fetchUserData(userId) {
  try {
    const response = await axios.get('https://jsonplaceholder.typicode.com/users', {
      // 查询参数,自动序列化为 ?id=1
      params: {
        id: userId,
        lang: 'zh-CN'
      },
      // 自定义请求头
      headers: {
        'Accept': 'application/json',
        'User-Agent': 'Node-Axios-Client/1.0'
      },
      // 请求超时限制(毫秒)
      timeout: 5000
    });

    // 成功接收响应:axios 自动解析了 JSON 数据,放置在 response.data 中
    console.log('HTTP 状态码:', response.status);
    console.log('响应数据:', response.data);
    return response.data;

  } catch (error) {
    if (error.response) {
      // 服务端有响应,但 HTTP 状态码超出了 2xx 范围(如 404, 500)
      console.error('服务端返回错误状态码:', error.response.status);
      console.error('错误详情:', error.response.data);
    } else if (error.request) {
      // 请求已发出但未收到任何响应(如连接超时、DNS 无法解析或断网)
      console.error('未收到服务器响应(可能超时或网络不可达)', error.message);
    } else {
      // 在设置请求时触发了其他未知错误
      console.error('请求初始化异常:', error.message);
    }
    throw error;
  }
}

// 调用执行
fetchUserData(1);

二、使用 Node.js 原生 http / https 模块发送 GET 请求

Node.js 内置了 http 与 https 模块,无需执行任何 npm install 命令即可直接引入。如果你的项目处于受限运行环境,或者需要构建零外部依赖的轻量级工具,原生模块是标准选择。

1. 原生模块的工作机制与协议区分

原生模块与高层封装库最大的不同在于:

  • 协议严格匹配:如果目标 URL 是 http://...,必须引入 http 模块;如果是 https://...,必须引入 https 模块。使用不匹配的模块调用会抛出协议错误。
  • 流式响应(Stream):原生回调接收到的 res 是一个 http.IncomingMessage 实例,它本质是一个可读流(Readable Stream)。服务端返回的响应体是分批次通过 'data' 事件吐出 Buffer 片段的,开发者必须手动将这些分块汇聚,并在 'end' 事件触发后合并转为字符串,再调用 JSON.parse()。
  • 默认不将 4xx/5xx 判定为异常:即使服务端返回 404 Not Found 或 500 Internal Server Error,原生模块依然会正常进入响应回调。只有在 TCP 连接断开、DNS 解析失败等网络底层故障时,才会触发 req.on('error')。
Node.js环境中怎么使用axios或http模块发送GET请求
图 2:Node.js 原生 http/https 模块的流式(Stream)响应与数据聚合架构

2. 原生模块封装为 Promise 的完整实现

为了在业务逻辑中以直观的 await 方式调用原生 HTTP 请求,我们通常将其封装为一个返回 Promise 的函数。同时使用 Node.js 全局的 URL 和 URLSearchParams 对象安全组装参数:

// native_http_get_demo.js
const https = require('https');
const http = require('http');

/**
 * 原生封装的通用 GET 请求函数
 * @param {string} baseUrl 目标接口基础地址
 * @param {object} params 查询参数键值对
 * @returns {Promise<any>}
 */
function nativeGet(baseUrl, params = {}) {
  return new Promise((resolve, reject) => {
    // 1. 利用 URL 对象安全拼装 URL 与 Query 参数
    const urlObj = new URL(baseUrl);
    Object.keys(params).forEach(key => {
      urlObj.searchParams.append(key, params[key]);
    });

    // 2. 根据协议自动选择 http 或 https 模块
    const client = urlObj.protocol === 'https:' ? https : http;

    const options = {
      headers: {
        'Accept': 'application/json',
        'User-Agent': 'Node-Native-Client/1.0'
      }
    };

    // 3. 发送 GET 请求
    const req = client.get(urlObj, options, (res) => {
      const statusCode = res.statusCode;
      
      // 校验 HTTP 状态码
      if (statusCode < 200 || statusCode >= 300) {
        // 重要提示:若状态码非 2xx,必须调用 resume 消费流以释放套接字内存
        res.resume();
        return reject(new Error(`请求失败,服务端返回 HTTP 状态码: ${statusCode}`));
      }

      const chunks = [];

      // 监听数据分块流入
      res.on('data', (chunk) => {
        chunks.push(chunk);
      });

      // 全部数据分块接收完毕
      res.on('end', () => {
        try {
          const rawBody = Buffer.concat(chunks).toString('utf8');
          const jsonData = JSON.parse(rawBody);
          resolve(jsonData);
        } catch (err) {
          reject(new Error(`响应数据解析为 JSON 失败: ${err.message}`));
        }
      });
    });

    // 4. 监听网络层或 DNS 解析等底层错误
    req.on('error', (err) => {
      reject(new Error(`网络连接错误: ${err.message}`));
    });

    // 5. 超时控制:触发 timeout 时主动销毁请求
    req.setTimeout(5000, () => {
      req.destroy(new Error('请求超时已中断(超过5000ms)'));
    });
  });
}

// 使用 async/await 调用执行
(async () => {
  try {
    const data = await nativeGet('https://jsonplaceholder.typicode.com/todos', { id: 1 });
    console.log('原生请求获取数据成功:', data);
  } catch (err) {
    console.error('捕获到请求异常:', err.message);
  }
})();

三、核心差异与选型对比

为了帮助开发者在实际项目中快速决断,下表从语法支持、依赖、数据处理及健壮性等维度整理了两者的直接差异:

比较维度 axios 方案 Node.js 原生 http / https 模块
外部依赖 需通过 npm 安装(第三方包,约几百 KB) 零依赖(Node.js 运行时核心内置)
API 抽象层级 高层封装,现代 Promise / async-await 原生支持 底层事件驱动流(基于 EventEmitter / Stream)
Query 参数处理 配置 params 对象自动编码拼接 需借助 URLSearchParams 手动拼接在 URL 路径上
响应内容反序列化 自动识别 application/json 并转换为对象 必须监听 data/end 聚合 Buffer 后显式 JSON.parse()
HTTP 错误状态判定 遇到 4xx/5xx 状态码默认直接 reject 进入 catch 4xx/5xx 依然触发成功回调,需手工判断 res.statusCode
流消费与内存泄漏防范 内部自动管理 Buffer 并在异常时释放 若状态码异常,必须显式调用 res.resume() 否则会导致 Socket 挂起
高级能力扩展 开箱即用支持请求/响应拦截器、全局默认配置 需开发者自行基于原型或代理模式封装
Node.js环境中怎么使用axios或http模块发送GET请求
图 3:Node.js 项目中 GET 请求实现方式的选择判断流程

四、生产环境关键避坑点与注意事项

在实际生产部署中,HTTP 客户端引发的问题常常出现在网络异常恢复、大并发连接或超时边界上。以下是使用这两套方案时最容易踩入的陷阱及对应解决方案:

1. 原生 http 模块的套接字泄漏(Socket Leak)

当使用原生 http.get 或 https.get 时,只要服务端返回了响应头(无论是 200、404 还是 500),Node.js 底层就会为该连接分配套接字通道。如果业务判断状态码非 200 并直接退出,但没有读取流或调用 res.resume(),该连接将被一直挂起,无法释放回连接池。在高并发场景下,短时间内就会把系统文件描述符或 Socket 池耗尽,导致后续所有网络请求卡死。

排查准则:在原生 http/https 的回调中,一旦决定抛弃当前响应,务必显式执行 res.resume(); 消费掉流数据。

2. 原生模块中的超时机制误区

很多初学者在原生请求中写了 req.setTimeout(3000),便认为请求会在 3 秒后自动中断。这是错误的理解。

原生 setTimeout 只是在超过指定时间没有收到数据包时触发 'timeout' 事件,它不会主动终止 HTTP 请求。必须在 req.on('timeout') 回调中显式调用 req.destroy(),底层连接才会被真正中断。而 axios 的 timeout 配置项则封装了完整的取消流程,超时后会自动调用中断逻辑并抛出 ECONNABORTED 错误。

3. 查询参数(Query String)编码与 URL 拼接

直接使用模板字符串 `https://api.example.com/search?q=${keyword}` 拼接参数极易引发安全与语法隐患。当 keyword 中包含空格、&、#、= 或中文字符时,服务端解析到的参数可能会被强行截断,甚至报 400 格式错误。使用 axios 时推荐全部放入 params 对象中;使用原生模块时,务必使用 new URLSearchParams() 或 encodeURIComponent() 进行标准编码。

Node.js环境中怎么使用axios或http模块发送GET请求
图 4:Node.js GET 请求生产落地与健壮性检查清单

总结

在 Node.js 中发送 GET 请求,axios 提供了更高阶、更贴近现代 JavaScript 异步习惯的开发体验,自动帮开发者处理了参数编码、响应反序列化、状态码校验与超时阻断,是绝大多数日常工程、企业级业务与团队协作的首选。

而 http / https 原生模块则代表了 Node.js 底层的运作模型。理解它的流式接收机制、事件监听模式以及 res.resume() 的套接字回收逻辑,不仅能让你在受限运行环境或无依赖轻量工具中游刃有余,更是深入掌握 Node.js 网络 I/O 原理的关键一步。

作者最新文章
相关文章
更多