阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > Fetch API与XMLHttpRequest的比较

Fetch API与XMLHttpRequest的比较

作者:陈川 阅读数:65156人阅读 分类: HTML

Fetch API与XMLHttpRequest的基本概念

Fetch API是现代浏览器提供的新标准,用于替代传统的XMLHttpRequest(XHR)进行网络请求。它基于Promise设计,语法更简洁直观。XMLHttpRequest则是早期浏览器提供的API,虽然功能强大但使用复杂。两者都能完成HTTP请求,但在实现方式和特性上有显著差异。

// Fetch API基本用法
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

// XMLHttpRequest基本用法
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data');
xhr.onload = function() {
  if (xhr.status === 200) {
    console.log(JSON.parse(xhr.responseText));
  }
};
xhr.send();

语法与使用体验

Fetch API采用链式Promise调用,代码结构更扁平化。错误处理通过catch统一捕获,支持async/await语法糖。XMLHttpRequest则需要配置回调函数,容易产生"回调地狱"。

// Fetch的async/await写法
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Fetch failed:', error);
  }
}

// XHR的事件监听方式
const xhr = new XMLHttpRequest();
xhr.addEventListener('load', handleLoad);
xhr.addEventListener('error', handleError);
xhr.open('GET', 'https://api.example.com/data');
xhr.send();

function handleLoad() { /*...*/ }
function handleError() { /*...*/ }

请求与响应处理

Fetch API的Response对象提供了丰富的方法:

  • response.json() 解析JSON
  • response.text() 获取文本
  • response.blob() 处理二进制数据
  • response.formData() 处理表单数据

XMLHttpRequest需要手动处理响应类型:

xhr.responseType = 'json'; // 或'text'、'arraybuffer'等
xhr.onload = function() {
  console.log(xhr.response); // 根据responseType自动解析
};

错误处理机制

Fetch只在网络故障时reject,HTTP错误状态(如404)不会触发catch。需要额外检查response.ok或status。XMLHttpRequest通过status属性直接判断请求状态。

// Fetch的错误处理
fetch('https://api.example.com/404')
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();
  })
  .catch(error => console.log('Error:', error.message));

// XHR的错误处理
xhr.onreadystatechange = function() {
  if (xhr.readyState === 4) {
    if (xhr.status >= 200 && xhr.status < 300) {
      console.log(xhr.response);
    } else {
      console.error('Request failed with status:', xhr.status);
    }
  }
};

请求控制与超时

XMLHttpRequest原生支持timeout属性,而Fetch需要结合AbortController实现超时控制:

// Fetch超时控制
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);

fetch('https://api.example.com/slow', {
  signal: controller.signal
})
  .then(response => {
    clearTimeout(timeoutId);
    return response.json();
  })
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Request timed out');
    }
  });

// XHR超时设置
xhr.timeout = 5000;
xhr.ontimeout = function() {
  console.log('Request timed out');
};

请求进度监控

XMLHttpRequest提供进度事件:

xhr.upload.onprogress = function(event) {
  console.log(`Uploaded ${event.loaded} of ${event.total} bytes`);
};
xhr.onprogress = function(event) {
  console.log(`Downloaded ${event.loaded} of ${event.total} bytes`);
};

Fetch API目前没有原生进度API,但可以通过响应体的流式处理模拟:

const response = await fetch('https://api.example.com/large-file');
const reader = response.body.getReader();
let receivedLength = 0;

while(true) {
  const {done, value} = await reader.read();
  if (done) break;
  receivedLength += value.length;
  console.log(`Received ${receivedLength} bytes`);
}

跨域请求处理

两者都遵循同源策略,但Fetch的CORS模式配置更明确:

fetch('https://api.example.com/data', {
  mode: 'cors',
  credentials: 'include' // 携带cookie
});

XMLHttpRequest需要设置withCredentials属性:

xhr.withCredentials = true;

浏览器兼容性

XMLHttpRequest兼容所有现代浏览器甚至IE6。Fetch API在IE完全不支持,但在现代浏览器中得到广泛实现。可以使用polyfill解决兼容问题:

<script src="https://cdn.jsdelivr.net/npm/whatwg-fetch@3.6.2/dist/fetch.umd.min.js"></script>

性能比较

在简单请求场景下两者性能差异不大。对于大量并发请求,Fetch可能略有优势,因为基于Promise的实现更轻量。XMLHttpRequest在需要精细控制请求过程时表现更好。

高级功能对比

Fetch API支持Service Worker拦截和修改请求:

// Service Worker中
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => response || fetch(event.request))
  );
});

XMLHttpRequest支持同步请求(会阻塞UI线程):

xhr.open('GET', 'https://api.example.com/data', false); // 同步
xhr.send();
if (xhr.status === 200) {
  console.log(xhr.responseText);
}

实际应用场景选择

对于简单REST API调用,优先使用Fetch API。需要上传进度监控或兼容旧浏览器时选择XMLHttpRequest。现代框架如axios实际上对两者都进行了封装,提供了更统一的接口。

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌