在 Web 应用中,JavaScript 通过 XMLHttpRequest (XHR)来执行异步请求,这是一种有效改进页面通信的技术,当我们谈及Ajax技术的时候,通常意思就是基于 XMLHttpRequest 的 Ajax。虽说 Ajax 很有用,但它不是最佳 API,它在设计上不符合职责分离原则,将输入、输出和用事件来跟踪的状态混杂在一个对象里。而且,基于事件的模型与现在 JavaScript 流行的 Promise 以及基于生成器的异步编程模型相背驰。本文将要介绍的内容则是XMLHttpRequest 的最新替代技术—— Fetch API, 它是 W3C 的正式标准。

兼容性

在介绍之前,先看看目前主流浏览器对 Fetch API 的支持情况:

1192.jpg

Fetch 的支持目前还处于早期的阶段,在 Firefox 39 以上,和 Chrome 42 以上都被支持了。


如果你现在就想使用它,还可以用 Fetch Polyfil,用于支持那些还未支持 Fetch 的浏览器。


在使用 Fetch 之前,也可以对其进行功能性检测:

if(self.fetch) {    // run my fetch request here} else {    // do something with XMLHttpRequest?}

简单的fetching示例


在 Fetch API 中,最常用的就是 fetch() 函数。它接收一个URL参数,返回一个 promise 来处理 response。response 是一个 Response 对象:

fetch("/data.json").then(function(res) {  // res instanceof Response == true.  if (res.ok) {    res.json().then(function(data) {      console.log(data.entries);    });  } else {    console.log("Looks like the response wasn't perfect, got status", res.status);  }}, function(e) {  console.log("Fetch failed!", e);});


fetch() 接受第二个可选参数,一个可以控制不同配置的 init 对象。如果是提交一个 POST 请求,代码如下:

fetch("http://www.example.org/submit.php", {  method: "POST",  headers: {    "Content-Type": "application/x-www-form-urlencoded"  },  body: "firstName=Nikhil&favColor=blue&password=easytoguess"}).then(function(res) {  if (res.ok) {    //res.ok用于检测请求是否成功    console.log("Perfect! Your settings are saved.");  } else if (res.status == 401) {    console.log("Oops! You are not authorized.");  }}, function(e) {  console.log("Error submitting form!");});

如果遇到网络故障,fetch() promise 将会 reject,带上一个 TypeError 对象。想要精确的判断 fetch() 是否成功,需要包含 promise resolved 的情况,此时再判断 Response.ok 是不是为 true。


Fetch 实现了四个接口:GlobalFetch、Headers、Request 和 Response。GloabaFetch 就只包含了一个 fetch 方法用于获取网络资源,其它三个直接对应了相应的 HTTP 概念。此外,在 request/reponse 中,还混淆了 Body。

Headers

Headers 接口允许定义 HTTP 的请求头(Request.headers)和响应头(Response.headers)。一个 Headers 对象是一个简单的多名值对:

var content = "Hello World";var myHeaders = new Headers();myHeaders.append("Content-Type", "text/plain");myHeaders.append("Content-Length", content.length.toString());myHeaders.append("X-Custom-Header", "ProcessThisImmediately");


也可以传一个多维数组或者对象字面量:

myHeaders = new Headers({  "Content-Type": "text/plain",  "Content-Length": content.length.toString(),  "X-Custom-Header": "ProcessThisImmediately",});

此外,Headers 接口提供了 set ,delete 等 API 用于检索其内容:

console.log(reqHeaders.has("Content-Type")); // trueconsole.log(reqHeaders.has("Set-Cookie")); // falsereqHeaders.set("Content-Type", "text/html");reqHeaders.append("X-Custom-Header", "AnotherValue");console.log(reqHeaders.get("Content-Length")); // 11console.log(reqHeaders.getAll("X-Custom-Header")); // ["ProcessThisImmediately", "AnotherValue"]reqHeaders.delete("X-Custom-Header");console.log(reqHeaders.getAll("X-Custom-Header")); // []


虽然有些操作仅在 ServiceWorkers 中使用,但相对于 XHR,其本身提供了非常方便的操作 Headers 的 API。


出于安全原因,有些 header 字段的设置仅能通过 User Agent 实现,不能通过编程设置:请求头禁置字段 和 响应头禁置字段。


如果使用了一个不合法的 HTTP Header 属性名或者写入一个不可写的属性,Headers 的方法通常都抛出 TypeError 异常:

var myResponse = Response.error();try {  myResponse.headers.set("Origin", "http://mybank.com");} catch(e) {  console.log("Cannot pretend to be a bank!");}

最佳实践是在使用之前检查 content type 是否正确,比如:

fetch(myRequest).then(function(response) {  if(response.headers.get("content-type") === "application/json") {    return response.json().then(function(json) {      // process your JSON further    });  } else {    console.log("Oops, we haven't got JSON!");  }});

由于 Headers 可以在 request 请求中被发送或者在 response 请求中被接收,并且规定了哪些参数是可写的,Headers 对象有一个特殊的 guard 属性。这个属性没有暴露给 Web,但是它影响到哪些内容可以在 Headers 对象中被改变。


可能的值如下:


none:默认的

r

equest:从 request 中获得的 headers(Request.headers)只读request-no-cors:从不同域(Request.mode no-cors)的 request 中获得的 headers 只读response:从 response 中获得的 headers(Response.headers)只读immutable:在 ServiceWorkers 中最常用的,所有的 headers 都只读


Request


Request 接口定义了通过HTTP请求资源的request格式,一个简单请求构造如下:

var req = new Request("/index.html");console.log(req.method); // "GET"console.log(req.url); // "http://example.com/index.html"console.log(req.headers); //请求头

和 fetch() 一样,Request 接受第二个可选参数,一个可以控制不同配置的 init 对象:

var myHeaders = new Headers();var myInit = { method: 'GET',               headers: myHeaders,               mode: 'cors',               cache: 'default' ,               credentials: true,               body: "image data"};var myRequest = new Request('flowers.jpg',myInit);fetch(myRequest,myInit).then(function(response) {  return response.blob();}).then(function(myBlob) {  var objectURL = URL.createObjectURL(myBlob);  myImage.src = objectURL;});


mode 属性用来决定是否允许跨域请求,以及哪些response 属性可读。mode 可选的属性值:

same-origin:请求遵循同源策略

no-cors: 默认值,允许来自CDN的脚本、其他域的图片和其他一些跨域资源(前提条件是 method 只能是HEAD,GET或者POST)

cors :允许跨域,请求遵循 CROS协议

credentials 枚举属性决定了cookies 是否能跨域得到,这与 XHR 的 withCredentials 标志相同,但是只有三个值,分别是omit(默认),same-origin以及include。

Response

Response 实例是在 fentch() 处理完 promises 之后返回的,它的实例也可用通过 JavaScript 来创建, 但只有在 ServiceWorkers 中才真正有用。当使用 respondWith() 方法并提供了一个自定义的response来接受request时:

 var myBody = new Blob();addEventListener('fetch', function(event) {  event.respondWith(new Response(myBody, {    headers: { "Content-Type" : "text/plain" }  });});


Response() 构造方法接受两个可选参数—response的数据体和一个初始化对象(与 Request() 所接受的init参数类似.)

最常见的response属性有:

Response.status — 整数(默认值为200) 为response的状态码.Response.statusText — 字符串(默认值为OK),该值与HTTP状态码消息对应.Response.ok — 如上所示, 该属性是来检查response的状态是否在200-299(包括200,299)这个范围内.该属性返回一个Boolean值.Response.headers — 响应头Response.type — 响应类型,如:basic/ cors /error

Body

Request 和 Response 都实现了 Body 接口,在请求过程中,二者都会携带 Body,其可以是以下任何一种类型的实例:

ArrayBufferArrayBufferViewBlob/fileURLSearchParamsFormData

此外,Request 和 Response 都为他们的body提供了以下方法,这些方法都返回一个Promise对象:

arrayBuffer()blob()json()text()formData()


以上就是XML Http Request最新替代技术—— Fetch 的内容,更多相关内容请关注PHP中文网(www.php.cn)!

更多相关文章

  1. xml学习(7) .net 获取xml节点或者属性最大值
  2. 利用XMLSerializer将对象串行化到XML
  3. Web设计中如何使用XML数据源对象详细介绍
  4. XmlSerializer 对象的Xml序列化和反序列化的示例代码分析
  5. XML中的树形结构与DOM文档对象模型的示例代码(图)
  6. 详细介绍XML中的属性学习方法
  7. XML实例教程:nodeName、nodeValue和nodeType属性的详解
  8. XmlDocument 对象操作详细步骤
  9. XML入门教程-属性声明代码示例

随机推荐

  1. android 入门之二【android 体系架构】
  2. 【Android 开发】:通知之Notifications To
  3. handler机制
  4. android界面设计之shape的使用
  5. 在 Android 上使用 XML
  6. Android RelativeLayout属性大全(中文解释
  7. [Android 新特性] 谷歌发布Android Studi
  8. 收藏了4年的Android 源码分享
  9. Android(安卓)ApiDemos示例解析(150):Vie
  10. 论Android Studio Intellij IDE 与 Andro