Js 网络请求:Fetch

Js 网络请求:Fetch

​ 前言,为了减少 SDK 的体积,计划使用底层 API 进行开发,之前有听过 Fetch,特地过来调研记录下

官方文档:

Fetch API:使用 Fetch - Web API 接口参考 | MDN (mozilla.org)

XMLHttpRequest API: 使用 XMLHttpRequest - Web API 接口参考 | MDN (mozilla.org)

01 历史原因

XMLHttpRequest ,又称 xhr。很早就问世了,所以在以往的应用中,常常使用 Promise 封装好的形式(axios)出现在我们视野中。但是它有些明显的缺点,配置繁杂,不支持 Promise 和接口单一,容易写出非常混乱的代码。

后来,Fetch 作为后浪出道了,江湖人称 xhr 的升级版,但!Fetch 并不属于 xhr ,他们俩同级,都属于 JS 的底层 API,最多管叫哥们。

Fetch 优点:

  • 采用 Promise ,使得代码更简洁优雅
  • 采用模块化设计,API 设计更加合理,接口分离到三个对象上,Response 对象,Request 对象,Header 对象
  • 通过数据流处理数据,支持分块读取,对于请求大文件和网速慢有奇效

缺点:

  • 兼容性没有 xhr 支持那么好
  • 原生 Fetch 不支持监测进度,但 xhr 可以

02 代码对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 传统的 xhr 请求
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'json';

xhr.onload = function() {
console.log(xhr.response);
};

xhr.onerror = function() {
console.log("Oops, error");
};

xhr.send();

// fetch 请求
fetch('http://example.com/movies.json')
.then( response => response.json() )
.then( data => console.log(data) );
.catch( err => console.log(err))

相比下,Fetch API 更加简洁明了。

但是,与传统 ajax 相比:

  • 当接收到一个代表错误的 HTTP 状态码时,从 fetch() 返回的 Promise 不会被标记为 reject,即使响应的 HTTP 状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (如果响应的 HTTP 状态码不在 200 - 299 的范围内,则设置 resolve 返回值的 ok 属性为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。
  • fetch 不会发送跨域 cookies,需要配置 credentials="include"

我们可以改造上面的写法

Promise 可以使用 await 语法改写,使得语义更清晰。

1
2
3
4
5
6
7
8
// 下面示例中,await语句必须放在try...catch里面,这样才能捕捉异步操作中可能发生的错误。
try {
let response = await fetch(url)
let data = await response.json()
console.log(data)
} catch (e) {
console.log('Oops, error', e)
}

03 封装 Fetch API


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!