JS 发送 HTTP 请求的四种方式:从基础到现代实践

更新日期: 2026-05-06 阅读: 60 标签: 请求

前言

在 Web 开发中,前端与后端的数据交互是核心环节。JavaScript 提供了多种发送 HTTP 请求的方式,从早期的 XMLHttpRequest 到现代的 Fetch API,再到第三方库和语法层面的支持。理解它们之间的区别和适用场景,能够帮助你在实际项目中做出更合适的选择。

本文会依次介绍四种主流方式,并附上可以直接运行的代码示例。


一、XMLHttpRequest:经典的基石

XMLHttpRequest(简称 XHR)是浏览器最早提供的异步请求接口。尽管名字里带有 XML,但它支持所有类型的数据格式,比如 JSON、HTML、纯文本等。它的核心作用是让页面在不整体刷新的情况下,向服务器发送请求并获取数据,这正是 Ajax 技术的核心。

基本用法

下面是一个完整的异步 GET 请求示例:

// 1. 创建一个 XHR 实例
const xhr = new XMLHttpRequest();

// 2. 配置请求:方法、地址、是否异步
xhr.open('GET', 'https://api.example.com/data', true);

// 3. 监听加载完成事件
xhr.onload = function () {
  if (xhr.status >= 200 && xhr.status < 300) {
    // 请求成功
    const data = JSON.parse(xhr.responseText);
    console.log('获取到的数据:', data);
  } else {
    // 服务器返回了错误状态码
    console.error('请求失败,状态码:', xhr.status);
  }
};

// 4. 监听网络错误
xhr.onerror = function () {
  console.error('网络连接出现问题');
};

// 5. 发送请求
xhr.send();

同步请求的注意事项

XHR 支持同步模式,只需将 open() 的第三个参数设为 false。但同步请求会阻塞主线程,在请求完成之前用户无法进行任何操作,体验很差,现代浏览器已在主线程中逐步弃用这种做法。

// 不推荐:同步请求
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', false);
xhr.send();

if (xhr.status === 200) {
  console.log(xhr.responseText);
}

除非在 Worker 线程中有特殊需求,否则应始终使用异步模式。

补充:sendBeacon 方法

还有一个与 XHR 相关但独立的 API 值得一提:navigator.sendBeacon()。它专门用于在页面即将卸载时,向服务器发送少量数据,比如埋点统计或用户行为的最后记录。

// 页面关闭前发送统计数据
window.addEventListener('unload', function () {
  const data = { event: 'page_close', timestamp: Date.now() };
  navigator.sendBeacon('/api/analytics', JSON.stringify(data));
});

它的优势在于:即使页面正在关闭,浏览器也会保证请求发出,不会因为页面卸载而中断。


二、Fetch API:现代的 Promise 风格

Fetch 是 ES6 引入的新接口,基于 Promise 设计,语法更简洁、逻辑更清晰。它被认为是 XMLHttpRequest 的现代化替代方案。

基本 GET 请求

fetch('https://api.example.com/data')
  .then(function (response) {
    // 先检查响应是否成功
    if (!response.ok) {
      throw new Error('网络响应异常,状态码: ' + response.status);
    }
    // 将响应体解析为 JSON
    return response.json();
  })
  .then(function (data) {
    console.log('获取到的数据:', data);
  })
  .catch(function (error) {
    console.error('请求出错:', error.message);
  });

一个重要的认知:错误处理

Fetch 有一个容易误解的地方:当服务器返回 404 或 500 这样的错误状态码时,Fetch 返回的 Promise 并不会进入 reject 状态,而是会正常 resolve,只是 response.ok 会变为 false。只有在网络故障或请求被拦截时,Promise 才会 reject。

因此,自己动手检查 response.ok 是一个好习惯,上面已经展示了具体写法。

POST 请求示例

function postData(url, data) {
  return fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  })
    .then(function (response) {
      if (!response.ok) {
        throw new Error('请求失败,状态码: ' + response.status);
      }
      return response.json();
    });
}

// 使用
postData('https://api.example.com/submit', {
  name: '张三',
  age: 28
})
  .then(function (result) {
    console.log('提交结果:', result);
  })
  .catch(function (error) {
    console.error('提交失败:', error.message);
  });

关于跨域和 Cookie

默认情况下,Fetch 不会发送跨站 Cookie。如果需要携带身份凭证,可以设置 credentials 选项:

fetch('https://api.example.com/user', {
  credentials: 'include'  // 始终发送 cookie
});


三、Axios:功能更强的第三方库

在实际项目中,很多开发者会选择 Axios 这个 HTTP 客户端库。它封装了 XHR,提供了更友好的 API 和更丰富的功能。

安装方式

你可以通过 CDN 直接引入,也可以通过 npm 安装:

bash
npm install axios

发送 GET 请求

// 使用 CDN 引入后,axios 会挂载到全局
axios.get('https://api.example.com/data')
  .then(function (response) {
    // 响应数据在 response.data 中,无需手动解析 JSON
    console.log('数据:', response.data);
  })
  .catch(function (error) {
    // 状态码非 2xx 时会自动进入 catch
    console.error('请求出错:', error.message);
  });

发送 POST 请求

axios.post('https://api.example.com/submit', {
  name: '张三',
  age: 28
})
  .then(function (response) {
    console.log('提交成功:', response.data);
  })
  .catch(function (error) {
    console.error('提交失败:', error.message);
  });

Axios 的优势

与原生 Fetch 相比,Axios 有几个实用特性:

  1. 自动转换 JSON:请求数据会自动转为 JSON,响应数据会自动解析,不用手动调用 JSON.stringify 和 response.json()。

  2. 错误处理更直观:所有非 2xx 的状态码都会让 Promise 进入 reject,符合多数开发者的直觉。

  3. 请求和响应拦截器:可以在请求发出前或响应到达后统一处理,比如添加 Token、记录日志、处理全局错误。

  4. 取消请求:通过 CancelToken 或 AbortController 可以主动取消正在进行的请求。

  5. 超时配置:直接设置 timeout 属性即可,Fetch 原生不支持。

// 请求拦截器示例:统一添加 Token
axios.interceptors.request.use(function (config) {
  const token = localStorage.getItem('token');
  if (token) {
    config.headers.Authorization = 'Bearer ' + token;
  }
  return config;
});

// 响应拦截器示例:统一处理错误
axios.interceptors.response.use(
  function (response) {
    return response;
  },
  function (error) {
    if (error.response && error.response.status === 401) {
      // 跳转到登录页
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);


四、Async/Await:让异步代码像同步一样

Async/Await 是 ES2017 引入的语法,它建立在 Promise 之上,让异步代码的结构更接近同步代码,可读性更好。它与 Fetch 或 Axios 搭配使用,效果非常好。

基本语法

  • async 放在函数前面,表示该函数会返回一个 Promise。

  • await 放在返回 Promise 的表达式前面,会暂停函数执行,等待这个 Promise 完成,然后返回结果。

// 定义一个返回 Promise 的辅助函数
function delay(ms) {
  return new Promise(function (resolve) {
    setTimeout(resolve, ms);
  });
}

// 使用 async/await
async function delayedMessage(value, ms) {
  await delay(ms);
  console.log(value);
}

delayedMessage('你好,世界', 2000);
// 2 秒后输出:你好,世界

搭配 Fetch 使用

async function fetchUserData(userId) {
  try {
    const response = await fetch('https://api.example.com/users/' + userId);

    if (!response.ok) {
      throw new Error('获取用户信息失败,状态码: ' + response.status);
    }

    const userData = await response.json();
    console.log('用户数据:', userData);
    return userData;
  } catch (error) {
    console.error('发生错误:', error.message);
    // 可以根据需要做进一步处理
  }
}

// 调用
fetchUserData(123);

搭配 Axios 使用

async function submitForm() {
  try {
    const response = await axios.post('https://api.example.com/form', {
      title: '申请单',
      content: '这是申请内容'
    });
    console.log('提交成功:', response.data);
    return response.data;
  } catch (error) {
    if (error.response) {
      // 服务器有响应,但状态码不是 2xx
      console.error('服务器错误:', error.response.status);
    } else if (error.request) {
      // 请求发出但没有收到响应
      console.error('无响应,请检查网络');
    } else {
      console.error('请求配置出错:', error.message);
    }
  }
}

错误处理的最佳实践

用 try...catch 包裹 await 表达式,可以统一捕获同步和异步的错误。这样无论错误来自网络、服务器还是代码逻辑,都能在一处处理。


五、四种方式的对比与选择

特性XMLHttpRequestFetchAxiosAsync/Await
语法复杂度高(回调嵌套)中(Promise 链)中(Promise 链)低(同步风格)
错误处理手动处理需自行检查 ok自动抛出非 2xx 错误用 try/catch 统一处理
自动 JSON 转换取决于搭配的底层
请求超时支持不支持原生方法支持取决于搭配的底层
上传/下载进度支持不完全支持支持取决于搭配的底层
浏览器兼容性全部现代浏览器全部(需引入库)现代浏览器

如何选择

  • 如果你需要兼容非常老旧的浏览器,而且不想引入第三方库,XMLHttpRequest 是唯一选择。

  • 如果你的项目是现代浏览器,而且不想增加额外的依赖,Fetch 足够应对大多数场景。

  • 如果你的项目需要请求拦截、超时处理、上传进度等高级功能,或者你更看重开发效率,Axios 是很好的选择。

  • Async/Await 是一个语法层面的改进,不是独立方法。它需要搭配 Fetch 或 Axios 使用,作用是让代码更加清晰。建议任何支持 ES2017 的项目都采用这种写法。


写在最后

从 XMLHttpRequest 到 Fetch,再到 Axios 这类封装库,JS 发送 HTTP 请求的方式在不断演进。每一种方案都有它的历史定位和适用场景。掌握它们,能让你在面对不同项目需求时,快速选到最合适的工具。

希望这篇文章对你的学习和工作有所帮助。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

相关推荐

flutter之网络请求dio封装,拦截器的封装

flutter一直很火的网络请求插件dio,直接上代码,写成一个类,可以直接使用,包含请求的封装,拦截器的封装

ajax异步请求302分析

遇到这样一种情况,打开网页两个窗口a,b(都是已经登录授权的),在a页面中退出登录,然后在b页面执行增删改查,这个时候因为授权原因,b页面后端的请求肯定出现异常(对这个异常的处理,进行内部跳转处理),b页面中的ajax请求的回调中就会出现问题

nginx 301跳转https后post请求失效问题解决

强制把http请求跳转到https,结果发现App有部分的功能不能使用,因为App一共设置了4种请求方式,分别是GET,POST,DELETE和OPTIONS方式,设置301跳转后所有的请求方法都变成了GET方式,导致一些功能无法正常使用.

Js两个异步请求 同步合并数据

业务代码经常会有 两个不一样的请求,拿到数据后合并成新数组的操作。但是在异步请求中我们不知道哪个请求的回调更快返回,从而使代码的合并时间无法确定。这就需要在两个异步请求都完成后再做数据处理。

http请求过程的7个步骤

HTTP通信机制是在一次完整的HTTP通信过程中,Web浏览器与Web服务器之间将完成下列7个步骤:建立TCP连接、Web浏览器向Web服务器发送请求命令、Web浏览器发送请求头信息、 Web服务器应答

http请求的几种类型

http请求中的8种请求方法:opions 返回服务器针对特定资源所支持的HTML请求方法 ,Get 向特定资源发出请求,Post 向指定资源提交数据进行处理请求

node.js含有%百分号时,发送get请求时浏览器地址自动编码的问题

目前浏览器会对地址,进行编码,比如这个文件名:在发到后台时,会自动编码成:不过如果文件名中含有%百分号,编码过程则会出现问题,如

HTTP请求报文和响应报文

GET:请求获取Request—URL所标识的资源,POST:在Request—URL所标识的资源后附加资源,HEAD:请求获取由Request—URL所标识的资源的响应消息报头,PUT:请求服务器存储一个资源,由Request—URL作为其标识

ajax中options请求的理解

这个概念听着有点耳生,嗯是我自己这么说的。我们可以把浏览器自主发起的行为称之为“浏览器级行为”。之所以说options是一种浏览器级行为,是因为在某些情况下,普通的get或者post请求回首先自动发起一次options请求

HTTP请求的11个处理阶段

几乎所以有关Nginx书只要是讲深入点的就会讲到Nginx请求的11个处理阶段,要记住这些真是不易,人脑特别不擅长记住各种东西,只能做些索引罢了,能做到知道这个知识点在哪儿能找到不就行了,可是你去面试还是问这些理论,所以这里汇总下记录如下

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!