欢迎你们关注腾讯云技术社区-博客园官方主页,咱们将持续在博客园为你们推荐技术精品文章哦~php
做者:villainthrhtml
文章摘自: 前端小吉米前端
随着前端异步的发展, XHR 这种耦合方式的书写不利于前端异步的 Promise 回调. 并且,写起来也是很复杂. fetch API 原本是在 SW(ServiceWorkers) 中提出的, 不过, 后面以为好用, 就把他挂载到 window 对象下. 这样, 在前端的正常通讯中, 咱们也能够直接调用. 但, fetch 毕竟比较新, 看一下他的兼容性.jquery
在 PC 端上, 就 FF, Opera 和 Chrome 比较 fashion. mobile 的话, 基本上是不能用的. 固然, 前端一直是个拥抱变化的职业, 官方已经有一个现成的 polyfill 可使用. 这样的话, 就不必过多担忧.git
每用到一个新的 feature, 咱们首先得知道他能不能用. Modernizr 这个库作的挺好的. 这里, 咱们简单的了解一下就 ok 了.程序员
let isFetch = window.fetch?true:false;
能够说, fetch 就是 ajax + Promise. 使用的方式和 jquery 提供的 $.ajax() 差很少.github
fetch('./api/some.json') .then( function(response) { if (response.status !== 200) { console.log(`返回的响应码${response.status}`); return; } // 得到后台实际返回的内容 response.json().then(function(data) { console.log(data); }); } ) .catch(function(err) { console.log('Fetch Error :-S', err); });
上面的 demo 很好的参数了, fetch 的几个特色.web
then 和 catch 是 promise 自带的两个方法, 我这里就很少说了. 咱们来看一下,json 是干吗的.ajax
由于返回回来的数据不只仅包括后台的返回的 Text 内容, 还有一些 Headers. 因此在, then 方法里面返回来的 res 实际上并非咱们在业务中想要的内容. 就和在 XHR 里返回数据是一个道理, 咱们最终要的是 responseText
这个数据. 而 json() 方法实际作的事情,就是调用 JSON.parse() 处理数据, 而且返回一个新的 Promise. 看一下 polyfill 源码就应该了解.json
this.json = function() { return this.text().then(JSON.parse) }
这里须要注意的是,fetch 中的 response/request 都是 stream 对象。
上面的 demo 是一个 get 方法的请求, 固然, 除了 get , 还有其余的 HTTP Method, PUT, DELETE, POST, PATCH 等. 这里, 咱们就说一个 POST, 其余方法的基本格式仍是相似的.
fetch("http://www.example.org/submit.php", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "this is a post Msg" }).then(function(res) { if (res.ok) { // doSth } else if (res.status == 401) { // doSth } });
看起来 fetch 和 $.ajax 并无多大的区别...
but... fetch 里面的内容,真很多. 往底层看一看, fetch 其实是 Request,Headers,Response 3个接口的整合. 不过, 这3个只能在 SW 里面使用. 这里当作原理,参数一下便可.
Headers 的操做无非就是 CRUD, 这里我就不过多赘述,直接看代码吧:
var content = "Hello World"; var reqHeaders = new Headers(); reqHeaders.append("Content-Type", "text/plain" reqHeaders.append("Content-Length", content.length.toString()); reqHeaders.append("X-Custom-Header", "自定义头");
固然, 你也可使用字面量的形式:
reqHeaders = new Headers({ "Content-Type": "text/plain", "Content-Length": content.length.toString(), "X-Custom-Header": "自定义头", });
接下来就是, 头部的内容的检测相关.
console.log(reqHeaders.has("Content-Type")); // true console.log(reqHeaders.has("Set-Cookie")); // false reqHeaders.set("Content-Type", "text/html"); reqHeaders.append("X-Custom-Header", "新增自定义头"); console.log(reqHeaders.get("Content-Length")); // 11 console.log(reqHeaders.getAll("X-Custom-Header")); // ["自定义头", "新增自定义头"] reqHeaders.delete("X-Custom-Header"); console.log(reqHeaders.getAll("X-Custom-Header")); // []
不过, 鉴于安全性的考虑, 有时候在多人协做或者子版块管理时, 对于头部的限制仍是须要的. 这里, 咱们能够经过 guard
属性, 设置 Headers 的相关策略.
guard 一般能够取 "immutable", "request", "request-no-cors", "response", "none".
咱们这里不探讨所有, 仅仅看一下 request 这个选项.
当你设置了 request 以后, 若是你设置的 Header 涉及到 forbidden header name (这个是浏览器自动设置的), 那么该次操做是不会成功的.
forbidden header name 一般有.
对比与 fetch, 咱们没有办法去设置 Headers的 guard, 因此, 这只能在 SW 里使用.
Request 的基本用法和 fetch 差很少.
var uploadReq = new Request("/uploadImage", { method: "POST", headers: { "Content-Type": "image/png", }, body: "image data" }); fetch("/uploadImage", { method: "POST", headers: { "Content-Type": "image/png", }, body: "image data" });
那 fetch 有什么用呢?
关键的地方在于,fetch 实际上就是 request/reponse 的容器,request/response 至关于就是两个元数据,fetch 只是实际进行的操做。因此,为了达到更高的复用性,咱们能够 ajax 的请求,实例化为一个个具体的对象。
var getName = new Request(...,{//...}); var getGender = new Request(...,{//...}); // 发送请求 fetch(getName) .then((res)=>{}); fetch(getGender) .then((res)=>{});
在浏览器里, 一切请求都逃不过跨域和不跨域的问题. fetch 也是. 对于跨域的请求, 主要的影响仍是体如今 Response 中, 这 fetch Request 这, 没多大影响. 不过, 咱们须要在 fetch 设置 mode
属性, 来表示这是一个跨域的请求.
fetch('https://www.villainhr.com/cors-enabled/some.json', {mode: 'cors'}) .then(function(response) { return response.text(); })
经常使用的 mode 属性值有:
Access-Control-Allow-Origin
. 话句话说, 就是用来处理 script, image 等的请求的. 他是 mode 的默认值.另外, 还有一个关于 cookie 的跨域内容. 在 XHR2 中,咱们了解到, withCredentials 这个属性就是用来设置在进行跨域操做时, 对不一样域的 Server 是否发送本域的 cookie. 通常设置为 omit(不发送). 在 fetch 当中, 使用的是 credentials
属性.
credentials 经常使用取值为:
因此, 若是你想发送 ajax 时, 带上 cookie, 那么你就须要使用 same-origin, 若是想在跨域时也带上 cookie, 那么就须要 include.
// 跨域请求 fetch('https://www.villainhr.com/cors-enabled/some.json', {mode: 'cors',credentials:'include'}) .then(function(response) { return response.text(); })
response 应该算和 fetch 最为接近的一个对象. Response 的实际其实就是 fetch 回调函数传回的参数. Response 中比较经常使用的属性有四个: status, statusText, ok, type.
fetch('https://www.villainhr.com/cors-enabled/some.json', {mode: 'cors',credentials:'include'}) .then(function(response) { // ... })
这里, 咱们主要关心一下 type 上面挂载的一些属性.
- Cache-Control - Content-Language - Content-Type - Expires - Last-Modified - Pragma
no-cors
发送跨域请求时,会触发.另外,在 response 上面,还挂载了几个经常使用的方法: text(),json().
使用方式都是流式 API.
fetch('https://www.villainhr.com/cors-enabled/some.json') .then(function(res) { res.text().then((text)=>{...}) res.json().then((obj)=>{...}) })
咱们经过 ajax 请求数据时,可能会收到,ArrayBuffer,Blob/File,string,FormData 等等。而且,在发送的时候好比:
var form = new FormData(document.getElementById('login-form')); fetch("/login", { method: "POST", body: form })
fetch 会自动设置相关的 Content-Type 的头。另外,若是咱们能够手动生成一个响应流(方便后面其余操做)。
var res = new Response(new File(["chunk", "chunk"], "archive.zip",{ type: "application/zip" }));
由于,req/res 都是以流的形式存在的,即,req/res 的 body 只能被使用一次。至关于就是一个文件从缓存读到硬盘里面,那么原来文件就已经消失了。咱们能够经过 bodyUsed
去检查,该对象是否已经被使用。
var res = new Response("one time use"); console.log(res.bodyUsed); // false res.text().then(function(v) { console.log(res.bodyUsed); // true }); console.log(res.bodyUsed); // true res.text().catch(function(e) { console.log("Tried to read already consumed Response"); });
这样作的缘由主要是为了让之后 Web 更好的处理视频的相关数据。那若是我有时候想要使用屡次,那该怎么办?
例如,咱们 Service Worker 中,使用 caches API 缓存响应,而后后面我还要将该响应返回给浏览器,那么这里 response 流就被使用了两次。这里,就和普通的流操做同样,将该流克隆一份,使用:
addEventListener('fetch', function(evt) { var sheep = new Response("Dolly"); console.log(sheep.bodyUsed); // false var clone = sheep.clone(); console.log(clone.bodyUsed); // false clone.text(); console.log(sheep.bodyUsed); // false console.log(clone.bodyUsed); // true evt.respondWith(cache.add(sheep.clone()).then(function(e) { return sheep; }); });
基本的内容就是上述内容. 若是想更详细参考的话, 请查阅:
【有奖讨论】程序员,怎么应对三十岁? 点击查看详情
欢迎加入QQ群:374933367,与腾云阁原创做者们一块儿交流,更有机会参与技术大咖的在线分享!
腾讯工程师们怎么玩 Vue.js?
React 入门学习
React同构直出优化总结
此文已由做者受权腾讯云技术社区发布,转载请注明文章出处
原文连接:https://www.qcloud.com/community/article/557775001489391626
获取更多腾讯海量技术实践干货,欢迎你们前往腾讯云技术社区