编者按:除创宇前端与做者博客外,本文还在语雀发布。
本篇主要讲述 Fetch 的一些基本知识点以及咱们在生产开发中怎么去使用。为了可以更好的了解 Fetch,咱们但愿你对如下知识点有所了解,若是有相关的开发经验,那是最好不过的了。javascript
本文中对有些关键词提供了相应的连接,若是你对该关键词不够了解或想要了解更多,你能够经过点击它充实本身。文中有些知识点在 MDN Fetch 上已经写的很详细,所以有略过,但愿同窗们在阅读本文章时可以同时对照阅读。html
本文行文思路首先从规范入手,目的是让你们了解的更透彻,达到知其然知其因此然。前端
为了更好的掌握 Fetch,文章中还提供了一些示例代码供你们学习使用。在使用该示例代码前,咱们但愿你对 node.js 有一些了解,若是没有的话,你能够根据示例中的友情提示完成你的此次学习体验。java
读完本篇文章后你将了解到如下内容:node
但愿你经过读完本篇文章后,对 Fetch 有一个基本的了解。c++
Fetch 是一种新的用于获取资源的技术,它被用来代替咱们已经吐槽了好久的技术(XHR)。git
Fetch 使用起来很简单,它返回的是一个 Promise,即便你没有 XHR 的开发经验也能快速上手。说了那么多,咱们仍是先睹为快吧,让咱们快快下面的示例代码。github
fetch('https://github.com/frontend9/fe9-library', { method: 'get' }).then(function(response) { }).catch(function(err) { // Error });
是否是简单的不能再简单了?好,既然咱们 Fetch 有了简单的认识以后,那咱们再来了解下 Fetch 的基本概念。web
在 Fetch 中有四个基本概念,他们分别是 Headers、Request 、Response 和 Body。为了更好的理解 Fetch,咱们须要对这些概念作一个简单的了解。json
在一个完整的 HTTP 请求中,其实就已经包含了这四个概念。请求中有请求头和请求体,响应中有响应头和响应体。因此咱们有必要了解这些概念。
为了实现头部的灵活性,可以对头部进行修改是一个很是重要的能力。Headers 属于 HTTP 中首部的一份子,它是一个抽象的接口,利用它能够对 HTTP 的请求头和响应头作出添加、修改和删除的操做。
下面咱们先看一下它具备哪些接口:
typedef (sequence<sequence<ByteString>> or record<ByteString, ByteString>) HeadersInit; [Constructor(optional HeadersInit init), Exposed=(Window,Worker)] interface Headers { void append(ByteString name, ByteString value); void delete(ByteString name); ByteString? get(ByteString name); boolean has(ByteString name); void set(ByteString name, ByteString value); iterable<ByteString, ByteString>; };interface Headers { void append(ByteString name, ByteString value); void delete(ByteString name); ByteString? get(ByteString name); boolean has(ByteString name); void set(ByteString name, ByteString value); iterable<ByteString, ByteString>; }; // 来自 https://fetch.spec.whatwg.org/#headers-class
规范中定义的接口咱们能够对应着 MDN 进行查看,你能够点击这里更直观的看看看看它有哪些方法供咱们使用。
这里咱们对 Headers
的构造参数作个解释。首先参数类型为 HeadersInit
,咱们再看下这个类型支持哪些类型的值。咱们从规范中能够看到的定义是:
typedef (sequence<sequence<ByteString>> or record<ByteString, ByteString>) HeadersInit;
这里咱们对应到 JavaScript
这门语言,意思就是说这个对象能够是数组或者是键值对(即对象)。关于如何初始化这些参数,咱们能够看下规范中定义的流程。
To fill a
Headers
object (headers) with a given object (object), run these steps:
这里我须要对这个作个说明,后面对 fetch 的用法会涉及到一点以及咱们看 polyfill 都会有所帮助。
header
名,第二项是值。,最后直接经过 append
方法添加。append
方法添加。示例代码地址:https://github.com/GoDotDotDo...
打开浏览器输入:http://127.0.0.1:4000/headers
那么咱们该如何使用它呢?首先咱们须要经过 new Headers()
来实例化一个 Headers 对象,该对象返回的是一个空的列表。在有了对象实例后,咱们就能够经过接口来完成咱们想要的操做,咱们来一块儿看看下面的示例:
function printHeaders(headers) { let str = ''; for (let header of headers.entries()) { str += ` <li>${header[0]}: ${header[1]}</li> `; console.log(header[0] + ': ' + header[1]); } return `<ul> ${str} </ul>`; } const headers = new Headers(); // 咱们打印下看看是否返回的是一个空的列表 const before = printHeaders(headers); // 发现这里没有任何输出 document.getElementById('headers-before').innerHTML = before; // 咱们添加一个请求头 headers.append('Content-Type', 'text/plain'); headers.append('Content-Type', 'text/html'); headers.set('Content-Type', ['a', 'b']); const headers2 = new Headers({ 'Content-Type': 'text/plain', 'X-Token': 'abcdefg', }); const after = printHeaders(headers); // 输出:content-type:
若是你以为每次都要 append
麻烦的话,你也能够经过在构造函数中传入指定的头部,例如:
const headers2 = new Headers({ 'Content-Type': 'text/plain', 'X-Token': 'abcdefg' }); printHeaders(headers2); // 输出: // content-type: text/plain // x-token: abcdefg
这里我添加了一个自定义头部 X-Token
,这在实际开发中很常见也颇有实际意义。可是切记在 CORS 中须要知足相关规范,不然会产生跨域错误。
你能够经过append
、 delete
、set
、get
和has
方法修改请求头。这里对 set
和 append
方法作个特殊的说明:
set
: 若是对一个已经存在的头部进行操做的话,会将新值替换掉旧值,旧值将不会存在。若是头部不存在则直接添加这个新的头部。
append
:若是已经存在该头部,则直接将新值追加到后面,还会保留旧值。
为了方便记忆,你只须要记住 set
会覆盖,而 append
会追加。
Guard 是 Headers 的一个特性,他是一个守卫者。它影响着一些方法(像 append
、 set
、delete
)是否能够改变 header 头。
它能够有如下取值:immutable
、request
、request-no-cors
、response
或 none
。
这里你无需关心它,只是为你让你了解有这样个东西在影响着咱们设置一些 Headers。你也没法去操做它,这是代理的事情。举个简单的例子,咱们没法在 Response Headers 中插入一个 Set-Cookie
。
若是你想要了解更过的细节,具体的规范请参考 concept-headers-guard 和 MDN Guard
TypeError
。Body 准确来讲这里只是 mixin,表明着请求体或响应体,具体由 Response
和 Request
来实现。
下面咱们来看看它具备哪些接口:
interface mixin Body { readonly attribute ReadableStream? body; readonly attribute boolean bodyUsed; [NewObject] Promise<ArrayBuffer> arrayBuffer(); [NewObject] Promise<Blob> blob(); [NewObject] Promise<FormData> formData(); [NewObject] Promise<any> json(); [NewObject] Promise<USVString> text(); }; // 来自 https://fetch.spec.whatwg.org/#body
规范中定义的接口咱们能够对应着 MDN 进行查看,你能够点击这里更直观的看看它有哪些属性和方法供咱们使用。
这里须要注意看这些方法返回的都是 Promise
,记住这在基于 fetch
进行接口请求中很重要。记住了这个,有利于咱们在后面的文章中理解 fetch
的用法。
范例将在 Response
中体现。
Request 表示一个请求类,须要经过实例化来生成一个请求对象。经过该对象能够描述一个 HTTP 请求中的请求(通常含有请求头和请求体)。既然是用来描述请求对象,那么该请求对象应该具备修改请求头(Headers)和请求体(Body)的方式。下面咱们先来看下规范中 Request 具备哪些接口:
typedef (Request or USVString) RequestInfo; [Constructor(RequestInfo input, optional RequestInit init), Exposed=(Window,Worker)] interface Request { readonly attribute ByteString method; readonly attribute USVString url; [SameObject] readonly attribute Headers headers; readonly attribute RequestDestination destination; readonly attribute USVString referrer; readonly attribute ReferrerPolicy referrerPolicy; readonly attribute RequestMode mode; readonly attribute RequestCredentials credentials; readonly attribute RequestCache cache; readonly attribute RequestRedirect redirect; readonly attribute DOMString integrity; readonly attribute boolean keepalive; readonly attribute boolean isReloadNavigation; readonly attribute boolean isHistoryNavigation; readonly attribute AbortSignal signal; [NewObject] Request clone(); }; Request includes Body; dictionary RequestInit { ByteString method; HeadersInit headers; BodyInit? body; USVString referrer; ReferrerPolicy referrerPolicy; RequestMode mode; RequestCredentials credentials; RequestCache cache; RequestRedirect redirect; DOMString integrity; boolean keepalive; AbortSignal? signal; any window; // can only be set to null }; enum RequestDestination { "", "audio", "audioworklet", "document", "embed", "font", "image", "manifest", "object", "paintworklet", "report", "script", "sharedworker", "style", "track", "video", "worker", "xslt" }; enum RequestMode { "navigate", "same-origin", "no-cors", "cors" }; enum RequestCredentials { "omit", "same-origin", "include" }; enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached" }; enum RequestRedirect { "follow", "error", "manual" }; // 来自 https://fetch.spec.whatwg.org/#request-class
规范中定义的接口咱们能够对应着 MDN 进行查看,你能够点击这里更直观的看看它有哪些属性和方法供咱们使用,这里不作一一解释。
注意这里的属性都是只读的,规范中咱们能够看到构造函数的第一个参数为 Request
对象或字符串,咱们通常采起字符串,即须要访问的资源地址( HTTP 接口地址)。第二个参数接收一个 RequestInit
可选对象,而这个对象是一个字典。在 javascript
中,咱们能够理解为一个对象({})。RequestInit
里面咱们能够配置初始属性,告诉 Request
咱们这个请求的一些配置信息。
这里咱们须要对如下几个属性特别注意下。
mode 是一个 RequestMode
枚举类型,可取的值有 navigate
, same-origin
, no-cors
, cors
。它表示的是一个请求时否使用 CORS,仍是使用严格同源模式。当处于跨域状况下,你应当设置为 cors
。该值的默认值在使用 Request
初始化时,默认为 cors
。当使用标记启动的嵌入式资源,例如 <link>
、 <script>
标签(未手动修改 crossorigin 属性),默认为 no-cors
。详细信息请参考 whatwg 规范或 MDN 。
credentials 是一个 RequestCredentials
枚举类型,可取的值有 omit
, same-origin
, include
。它表示的是请求是否在跨域状况下发送 cookie
。看到这,若是对 XHR 了解的同窗应该很熟悉。这和 XHR 中的 withCredentials
很类似。可是 credentials
有三个可选值,它的默认值为 same-origin
。当你须要跨域传递 cookie
凭证信息时,请设置它为 include
。注意这里有一个细节,当设置为 include
时,请确保 Response Header
中 Access-Control-Allow-Origin
不能为 *
,须要指定源(例如:http://127.0.0.1:4001),不然会你将会在控制台看到以下错误信息。详细信息请参考 whatwg 规范或 MDN 。
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
你可使用文章中提供的代码中启动 cors 示例代码,而后在浏览器中输入 http://127.0.0.1:4001/request,若是不出意外的话,你能够在控制台中看到上面的错误提示。
body 是一个 BodyInit 类型。它可取的值有 Blob
,BufferSource
, FormData
, URLSearchParams
, ReadableStream
, USVString
。细心的同窗不知道有没有发现,咱们常见的 json
对象却不在其中。所以,咱们若是须要传递 json
的话,须要调用 JSON.stringify
函数来帮助咱们转换成字符串。
下面将给出一段示例代码。
示例代码地址:https://github.com/GoDotDotDo...
打开浏览器输入:http://127.0.0.1:4000/request
// 客户端 const headers = new Headers({ 'X-Token': 'fe9', }); const request = new Request('/api/request', { method: 'GET', headers, }); console.log(request); // Request {method: "GET", url: "http://127.0.0.1:4000/api/request", headers: Headers, destination: "", referrer: "about:client", …} console.log(request.method); // GET console.log(request.mode); // cors console.log(request.credentials); // same-origin // 若是你想打印headers信息,能够调用 printHeaders(request.headers)
这里咱们先以 GET
简单请求做为示例,咱们传递了一个自定义的 Headers
,指定了请求方法 method
为 GET
(默认为 GET
)。在上面的接口规范中,咱们能够经过 Request
对象拿到一些经常使用的属性,好比 method
、url
、headers
、body
等等只读属性。
Response 和 Request 相似,表示的是一次请求返回的响应数据。下面咱们先看下规范中定义了哪些接口。
[Constructor(optional BodyInit? body = null, optional ResponseInit init), Exposed=(Window,Worker)] interface Response { [NewObject] static Response error(); [NewObject] static Response redirect(USVString url, optional unsigned short status = 302); readonly attribute ResponseType type; readonly attribute USVString url; readonly attribute boolean redirected; readonly attribute unsigned short status; readonly attribute boolean ok; readonly attribute ByteString statusText; [SameObject] readonly attribute Headers headers; readonly attribute Promise<Headers> trailer; [NewObject] Response clone(); }; Response includes Body; dictionary ResponseInit { unsigned short status = 200; ByteString statusText = ""; HeadersInit headers; }; enum ResponseType { "basic", "cors", "default", "error", "opaque", "opaqueredirect" }; // 来自 https://fetch.spec.whatwg.org/#response-class
规范中定义的接口咱们能够对应着 MDN 进行查看,你能够点击这里更直观的看看它有哪些属性和方法供咱们使用,这里不作一一解释。
其中 status
, headers
属性最为经常使用。经过 status
状态码咱们能够判断出服务端请求处理的结果,像 200
, 403
等等常见状态码。这里举个例子,当 status
为 401
时,能够在前端进行拦截跳转到登陆页面,这在现现在 SPA
(单页面应用程序)中尤其常见。咱们也能够利用 headers
来获取一些服务端返回给前端的信息,好比 token
。
仔细看上面的接口的同窗能够发现 Response includes Body;
这样的标识。在前面咱们说过 Body
由 Request
和 Response
实现。因此 Body
具备的方法,在 Response
实例中均可以使用,而这也是很是重要的一部分,咱们经过 Body
提供的方法(这里准确来讲是由 Response
实现的)对服务端返回的数据进行处理。
下面咱们将经过一个示例来了解下简单用法:
示例代码位置:https://github.com/GoDotDotDo...
// 客户端 const headers = new Headers({ 'X-Token': 'fe9-token-from-frontend', }); const request = new Request('/api/response', { method: 'GET', headers, }); // 这里咱们先发起一个请求试一试 fetch(request) .then(response => { const { status, headers } = response; document.getElementById('status').innerHTML = `${status}`; document.getElementById('headers').innerHTML = headersToString(headers); return response.json(); }) .then(resData => { const { status, data } = resData; if (!status) { window.alert('发生了一个错误!'); return; } document.getElementById('fetch').innerHTML = data; });
这里咱们先忽略 fetch
用法,后面的章节中会进行详细介绍。咱们先关注第一个 then
方法回调里面的东西。能够看到返回了一个 response
对象,这个对象就是咱们的 Response
的实例。示例中拿了 status
和 headers
,为了方便,这里我将其放到 html 中。再看看该回调中最后一行,咱们调用了一个 response.json()
方法(这里后端返的数据是一个 JSON
对象,为了方便直接调用 json()
),该方法返回一个 Promise
,咱们将处理结果返给最后一个 then
回调,这样就能够得到最终处理事后的数据。
打开浏览器,输入 http://127.0.0.1:4000/response,若是你的示例代运行正常,你将会看到如下页面:
(查看 Response 返回的数据)
Fetch 相对 XHR 来讲具备简洁、易用、声明式、天生基于 Promise 等特色。XHR 使用方式复杂,接口繁多,最重要的一点我的以为是它的回调设计,对于实现 try...catch
比较繁琐。
可是 Fetch 也有它的不足,相对于 XHR 来讲,目前它具备如下劣势:
在了解 Fetch 和 XHR 的一些不一样后,仍是须要根据自身的业务需求来选择合适的技术,由于技术没有永远的好坏,只有合不合适。
下面章节咱们将介绍如何“优雅”的使用 Fetch 以及如何尽可能避免掉劣势。
前面了解了这么多基础知识,如今终于到了介绍如何使用 Fetch 了。老规矩,咱们先来看下规范定义的接口。
partial interface mixin WindowOrWorkerGlobalScope { [NewObject] Promise<Response> fetch(RequestInfo input, optional RequestInit init); };
规范中定义的接口咱们能够对应着 MDN 进行查看,你能够点击这里更直观的看看它的用法。
从规范中咱们能够看到 fetch 属于 WindowOrWorkerGlobalScope 的一部分,暴露在 Window 或 WorkerGlobalScope 对象上。因此在浏览器中,你能够直接调用 fetch。
规范中定义了 fetch 返回一个 Promise,它最多可接收两个参数( input 和 init )。为了可以对它的使用方法有个更全面的了解,下面来说一下这两个参数。
RequestInfo
,咱们能够回到前面的 Request
部分,来回顾一下它的定义。typedef (Request or USVString) RequestInfo;
发现它是一个 Request
对象或者是一个字符串,所以你能够传 Request
实例或者资源地址字符串,这里通常咱们推荐使用字符串。
RequestInit
,咱们回顾前面 Requst
部分,它是一个字典类型。在 JavaScript
中你须要传递一个 Object
对象。dictionary RequestInit { ByteString method; HeadersInit headers; BodyInit? body; USVString referrer; ReferrerPolicy referrerPolicy; RequestMode mode; RequestCredentials credentials; RequestCache cache; RequestRedirect redirect; DOMString integrity; boolean keepalive; AbortSignal? signal; any window; // can only be set to null };
在本小节以前咱们都没有介绍 fetch 的使用方式,可是在其余章节中或多或少出现过它的容貌。如今,咱们终于能够在这里正式介绍它的使用方式了。
fetch 它返回一个 Promise,意味着咱们能够经过 then
来获取它的返回值,这样咱们能够链式调用。若是配合 async/await
使用,咱们的代码可读性会更高。下面咱们先经过一个简单的示例来熟悉下它的使用。
示例代码位置:https://github.com/GoDotDotDo...
// 客户端 const headers = new Headers({ 'X-Token': 'fe9', }); setTimeout(() => { fetch('/data?name=fe', { method: 'GET', // 默认为 GET,不写也能够 headers, }) .then(response => response.json()) .then(resData => { const { status, data } = resData; if (!status) { window.alert('发生了一个错误!'); return; } document.getElementById('fetch').innerHTML = data; }); }, 1000);
上面的示例中,咱们自定义了一个 headers
。为了演示方便,这里咱们设定了一个定时器。在请求成功时,服务器端会返回相应的数据,咱们经过 Response
实例的 json
方法来解析数据。细心的同窗会发现,这里 fetch 的第一个参数咱们采用的是字符串,在第二个参数咱们提供了一些 RequestInit
配置信息,这里咱们指定了请求方法(method)和自定义请求头(headers)。固然你也能够传递一个 Request
实例对象,下面咱们也给出一个示例。
代码位置:https://github.com/GoDotDotDo...
const headers = new Headers({ 'X-Token': 'fe9', }); const request = new Request('/api/request', { method: 'GET', headers, }); setTimeout(() => { fetch(request) .then(res => res.json()) .then(res => { const { status, data } = res; if (!status) { alert('服务器处理失败'); return; } document.getElementById('fetch-req').innerHTML = data; }); }, 1200);
在浏览器中打开:http://127.0.0.1:4000/, 若是上面的示例运行成功,你将会看到以下界面:
好,在运行完示例后,相信你应该对如何使用 fetch 有个基本的掌握。在上一章节,咱们讲过 fetch 有必定的缺点,下面咱们针对部分缺点来尝试着处理下。
当网络出现异常,请求可能已经超时,为了使咱们的程序更健壮,提供一个较好的用户 体验,咱们须要提供一个超时机制。然而,fetch 并不支持,这在上一小节中咱们也聊到过。庆幸的是,咱们有 Promise ,这使得咱们有机可趁。咱们能够经过自定义封装来达到支持超时机制。下面咱们尝试封装下。
const defaultOptions = { headers: { 'Content-Type': 'application/json', }, }; function request(url, options = {}) { return new Promise((resolve, reject) => { const headers = { ...defaultOptions.headers, ...options.headers }; let abortId; let timeout = false; if (options.timeout) { abortId = setTimeout(() => { timeout = true; reject(new Error('timeout!')); }, options.timeout || 6000); } fetch(url, { ...defaultOptions, ...options, headers }) .then((res) => { if (timeout) throw new Error('timeout!'); return res; }) .then(checkStatus) .then(parseJSON) .then((res) => { clearTimeout(abortId); resolve(res); }) .catch((e) => { clearTimeout(abortId); reject(e); }); }); }
上面的代码中,咱们须要注意下。就是咱们手动根据超时时间来 reject
并不会阻止后续的请求,因为咱们并无关闭掉这次链接,属因而伪取消。fetch 中若是后续接受到服务器的响应,依然会继续处理后续的处理。因此这里咱们在 fetch 的第一个 then
中进行了超时判断。
const controller = new AbortController(); const signal = controller.signal; fetch('/data?name=fe', { method: 'GET', signal, }) .then(response => response.json()) .then(resData => { const { status, data } = resData; if (!status) { window.alert('发生了一个错误!'); return; } document.getElementById('fetch-str').innerHTML = data; }); controller.abort();
咱们回过头看下 fetch 的接口,发现有一个属性 signal
, 类型为AbortSignal,表示一个信号对象( signal object ),它容许你经过 AbortController 对象与DOM请求进行通讯并在须要时将其停止。你能够经过调用 AbortController.abort 方法完成取消操做。
当咱们须要取消时,fetch 会 reject 一个错误( AbortError DOMException ),中断你的后续处理逻辑。具体能够看规范中的解释。
因为目前 AbortController 兼容性极差,基本不能使用,可是社区有人帮咱们提供了 polyfill(这里我不提供连接,由于目前来讲还不适合生产使用,会出现下面所述的问题),咱们能够经过使用它来帮助咱们提早感觉新技术带来的快乐。可是你可能会在原生支持 Fetch
可是又不支持 AbortController 的状况下,部分浏览器可能会报以下错误:
若是出现以上问题,咱们也无能为力,可能缘由是浏览器内部作了严格验证,对比发现咱们提供的 signal
类型不对。
可是咱们能够经过手动 reject
的方式达到取消,可是这种属于伪取消,实际上链接并无关闭。咱们能够经过自定义配置,例如在 options
中增长配置,暴露出 reject
,这样咱们就能够在外面来取消掉。这里本人暂时不提供代码。有兴趣的同窗能够尝试一下,也能够在下面的评论区评论。
前面提到过的获取进度目前咱们还没法实现。
示例代码位置:https://github.com/GoDotDotDo...
下面咱们讲一讲如何作一个简单的拦截器,这里的拦截器指对响应作拦截。假设咱们须要对接口返回的状态码进行解析,例如 403 或者 401 须要跳转到登陆页面,200 正常放行,其余报错。因为 fetch 返回一个 Promise ,这就使得咱们能够在后续的 then
中作些简单的拦截。咱们看一下示例代码:
function parseJSON(response) { const { status } = response; if (status === 204 || status === 205) { return null; } return response.json(); } function checkStatus(response) { const { status } = response; if (status >= 200 && status < 300) { return response; } // 权限不容许则跳转到登录页面 if (status === 403 || status === 401) { window ? (window.location = '/login.html') : null; } const error = new Error(response.statusText); error.response = response; throw error; } /** * @description 默认配置 * 设置请求头为json */ const defaultOptions = { headers: { 'Content-Type': 'application/json', }, // credentials: 'include', // 跨域传递cookie }; /** * Requests a URL, returning a promise * * @param {string} url The URL we want to request * @param {object} [options] The options we want to pass to "fetch" * * @return {object} The response data */ function request(url, options = {}) { return new Promise((resolve, reject) => { const headers = { ...defaultOptions.headers, ...options.headers }; let abortId; let timeout = false; if (options.timeout) { abortId = setTimeout(() => { timeout = true; reject(new Error('timeout!')); }, options.timeout || 6000); } fetch(url, { ...defaultOptions, ...options, headers }) .then((res) => { if (timeout) throw new Error('timeout!'); return res; }) .then(checkStatus) .then(parseJSON) .then((res) => { clearTimeout(abortId); resolve(res); }) .catch((e) => { clearTimeout(abortId); reject(e); }); }); }
从上面的 checkStatus
代码中咱们能够看到,咱们首先检查了状态码。当状态码为 403 或 401 时,咱们将页面跳转到了 login 登陆页面。细心的同窗还会发现,咱们多了一个处理方法就是 parseJSON
,这里因为咱们的后端统一返回 json 数据,为了方便,咱们就直接统一处理了 json 数据。
本系列文章总体阐述了 fetch 的基本概念、和 XHR 的差别、如何使用 fetch 以及咱们常见的解决方案。但愿同窗们在读完整篇文章可以对 fetch 的认识有所加深。
建议:在总体了解了 fetch 以后,但愿同窗们可以读一下 github polyfill 源码。在读代码的同时,能够同时参考 Fetch 规范。
参考:
文 / GoDotDotDot
Less is more.编 / 荧声
做者其余文章:
本文由创宇前端做者受权发布,版权属于做者,创宇前端出品。
欢迎注明出处转载本文。本文连接:https://blog.godotdotdot.com/...
想要订阅更多来自知道创宇开发一线的分享,请搜索关注咱们的微信公众号:创宇前端(KnownsecFED)。欢迎留言讨论,咱们会尽量回复。
欢迎点赞、收藏、留言评论、转发分享和打赏支持咱们。打赏将被彻底转交给文章做者。
感谢您的阅读。