最近,react 项目,使用 fetch 来进行 http 请求。遇到的问题是 fetch 超时 须要作额外处理;为此,特地查询了 fetch 相关的资料,整理了下;javascript
浏览器发起 http 请求,有两种方式,XMLHttpRequest(xhr) 和 fetch;其中 xhr 是咱们常常使用的方式,fetch 是在 ES6 引入的,fetch 返回有一个 Promise 对象,写法更加简便友好;html
在个人项目中,我使用的是isomorphic-fetch
。如今我对于这个包的理解,能够 cross-runtime,也就是区分环境 node 仍是 浏览器;前端
fetch 用法,MDN 中,讲得比较清楚,在这里和这里java
// fetch 返回Response的信息 { body: ReadableStream; bodyUsed: false; headers: Headers; ok: true; redirected: false; status: 200; statusText: "OK"; type: "cors"; url: "http://some-website.com/some-url"; __proto__: Response; }
请求的资源都存储在 body 中,做为一种可读的流。因此须要调用一个恰当方法将可读流转换为咱们可使用的数据。node
通常使用 response.json();若是是 xml 格式的,使用 response.text();若是是图片资源,使用 response.blob();react
- method: GET, POST, PUT, DELETE, HEAD。 - url: url地址。 - headers: 请求头相关参数。 - referrer : no-referrer, client或者一个网址。默认为client。 - mode: cors, no-cors, same-origin, navigate。默认为cors。Chrome(v47~)目前的默认值是 same-origin。 - credentials: omit, same-origin, include。默认值omit。Chrome(v47~)目前的默认值是 include。 - redirect: follow, error, manual。Chrome(v47~)目前的默认值是 manual。 - integrity: Subresource Integrity(子资源完整性, SRI)的值 - cache: default, no-store, reload, no-cache, 或者 force-cache - body: 要加到要求中的內容。注意,method为GET或者HEAD时不使用这个值。
前端请求的时候都会设计到 token 权限验证,不少时候是存在 cookie 里面的.fetch 里面又一个参数 credentials 设计 cookie
credentials 有三个值:git
fetch 跨域也有对应的参数设置 modees6
fetch 返回问题描述
当一个请求发送完成,服务返回状态码,fetch 不会 reject 这个 response,仍然 resolve,可是 response.ok 会设置成 false.不少时候咱们会二次封装 fetch reject error.github
处理 404 500web
目前 fetch 没有传统 ajax 的 abort 方法,还在草案之中
timeout 解决方案
使用 promise 的 race, 由于 promise 里面的 resolve 和 reject 只能执行一次, 利用 race reject 一个 error.
上面的 abort 并无真正的 abort 这次请求,只是经过 promise promise reject 一个 error 而已.我在翻阅 fetch 的源码的时候发现了这个
var p = Promise.race([ fetch("/resource-that-may-take-a-while"), new Promise(function (resolve, reject) { setTimeout(() => reject(new Error("request timeout")), 5000); }), ]); p.then((response) => console.log(response)); p.catch((error) => console.log(error));
原生 fetch 方法 可使用 AbortController 来中断;fetch 源码,支持使用 signal 来进行中断;
// fetch 源码 if (request.signal && request.signal.aborted) { return reject(new DOMException("Aborted", "AbortError")); }
具体代码以下:
// 1 秒后停止 let controller = new AbortController(); setTimeout(() => controller.abort(), 1000); try { let response = await fetch("/article/fetch-abort/demo/hang", { signal: controller.signal, }); } catch (err) { if (err.name == "AbortError") { // handle abort() alert("Aborted!"); } else { throw err; } }
具体看 这里
fetch 封装,对于 json text 图片格式处理,以及 timeout、相关报错等做了处理,能够点击获取;
总体文章,可能会有些问题,若有疑问,欢迎留言或者微信交流,共同窗习进步!
fetch-MDN
fetch-源码
Fetch:停止(Abort)
Isomorphic-Fetch 的詭異部份
fetch 详解
对 fetch timeout 的思考
fetch 使用的常见问题及解决办法
AJAX 與 Fetch API