浏览器中xmlHttpRequest和Fetch的区别

704 阅读2分钟

前言

随着前后端分离模式的流行,在项目开发过程中必不可少的一项就是与后台进行交互,从早期的Ajax(XMLHttpRequest), 到现在ES6中的Fetch Api,都是为了解决异步数据请求的问题,可以说Fetch的出现就是为了以一种更标准的方式来替代XMLHttpRequest,下面就来具体分析下他们存在哪些区别?

网上很多资料说fetch是对XMLHttpRequest的封装,这应该是有问题的,实际上fetch是对http接口的封装,两者没有任何的关系,它是一个新的api

相同点

  • 都是浏览器提供的功能,可以发送http网络请求,接收服务器返回的数据
  • 在浏览器中都存在跨域问题

区别点

核心实现

XMLHttpRequets和fetch虽然功能类似,但是在核心实现上是不一样的

  • fetch底层是对http接口的封装

  • XMLHttpRequets基于回调函数,而Fetch是基于promise的设计

代码写法

最直观的就是写法有很大的不同,比如请求一个url接口地址

XMLHttpRequest写法

const url = 'http://xxx.com.cn'
const xmlHttp = new XMLHttpRequest()
xmlHttp.open('get', url, true)
xmlHttp.onreadystatechange = () => {
   if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
       console.log(xmlHttp.response)
   }
}
xmlHttp.onerror = () => {
    console.log('error')
}
xmlHttp.send()

fetch写法

const url = 'http://xxx.com.cn'
fetch(url).then((response) => {
    return response.json()
}).then(data => {
    console.log(data)
}).catch(err => {
    console.log(err)
})

可以看到fetch相对XMLHttpRequest来说在实现上更加的方便和简洁

兼容性

XMLHttpRequets兼容性非常好,基本是所有的浏览器都支持

fetch由于是新的api,所以兼容性比XMLHttpRequets要差点,但是主流的浏览器基本都已经支持了

20160111123542_840 (1).png

跨域设置

请求接口如有存在跨域并且要传递cookie时,需要进行配置

XMLHttpRequest

const xmlHttp = new XMLHttpRequest()
....
xhr.withCredentials = true // 配置跨域传递cookie
....

fetch

fetch(url, {
    credentials: 'include', // 配置跨域传递cookie
    mode: 'cors' // 以cors的形式配置跨域
})

进度读取

XMLHttpRequest

可以对下载和上传的进度进行监听, 监听的事件需要写在open方法之前

# 下载数据监听
const xhr = new XMLHttpRequest()
xhr.addEventListener('progress', (e) => {
}, false)
xhr.open()
xhr.send()
# 上传数据监听
const xhr = new XMLHttpRequest()
xhr.upload.addEventListener('progress', (e) => {
    
}, false)
....

fetch

无法监听到进度状态

超时中断请求

XMLHttpRequest

在请求中可以设置超时属性,可以通过abort()中断当前请求

const xhr = new XMLHttpRequest()
xhr.open('get', 'http://xxx.com/api', true)
xhr.timeout = 30000
xhr.onload = () => {
    // 请求完成 todo
}
xhr.ontimeout = (e) => {
    // 请求超时todo
}
xhr.send()

fetch

fetch没有超时属性和终止当前请求的方法,需要手动的实现