深入浅出Fetch API

多年来,XMLHttpRequest一直是web开发者的亲密助手。无论是直接的,还是间接的, 当我们谈及Ajax技术的时候,通常意思就是基于XMLHttpRequest的Ajax,它是一种能够有效改进页面通信的技术。 Ajax的兴起是由于Google的Gmail所带动的,随后被广泛的应用到众多的Web产品(应用)中,可以认为, 开发者已经默认将XMLHttpRequest作为了当前Web应用与远程资源进行通信的基础。 而本文将要介绍的内容则是XMLHttpRequest的最新替代技术——Fetch API, 它是W3C的正式标准,本文将会介绍Fetch API的相关知识,以及探讨它所能使用的场景和能解决的问题。

Statement

原文地址: http://www.sitepoint.com/introduction-to-the-fetch-api/

译者:景庄,前端开发工程师,主要关注于前端工程化技术、Node.js、React等。

Fetch API

Fetch API提供了一个fetch()方法,它被定义在BOM的window对象中,你可以用它来发起对远程资源的请求。 该方法返回的是一个Promise对象,让你能够对请求的返回结果进行检索。

为了能够进一步的解释Fetch API,下面我们写一些代码来具体的介绍它的用法: 下面这个例子将会通过Flicker API来检索一些图片,并将结果插入到页面中。到目前为止, Fetch API还未被所有的浏览器支持。因此,如果你想体验这一技术,最好使用最新版本的Chrome浏览器。 为了能够正确的调用Flicker API,你需要申请自己的API KEY,将其插入到代码中的适当位置,即your_api_key那个位置。

来看看第一个任务:我们使用API来从Flicker中检索一些有关”企鹅“的照片,并将它们展示在也没中,代码如下。

/* API URL, you need to supply your API key */
var URL = 'https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=your_api_key&format=json&nojsoncallback=1&tags=penguins';function fetchDemo() {fetch(URL).then(function(response) {return response.json();}).then(function(json) {insertPhotos(json);});
}fetchDemo();

上面的代码看起来很简单:首先是构造请求的URL,然后将URL传递给全局的fetch()方法,它会立刻返回一个Promise, 当Promise被通过,它会返回一个Response对象,通过该对象的json()方法可以将结果作为JSON对象返回。 response.json()同样会返回一个Promise对象,因此在我们的例子中可以继续链接一个then()方法。

为了能够和传统的XMLHttpRequest进行对比,我们使用传统的方法来编写一个同样功能的函数:

function xhrDemo() {var xhr = new XMLHttpRequest();xhr.onload = function() {insertPhotos(JSON.parse(xhr.responseText));};xhr.open('GET', URL);xhr.send();
}

可以发现,主要的不同点在于:传统上我们会使用事件处理器,而不是Promise对象。 并且请求的发起完全依赖于xhr对象所提供的方法。

到目前为止,相比传统的XMLHttpRequest对象,我们使用Fetch API获得了更简洁的编码体验。但Fetch API不止于此, 下面我们进一步的深入下去。

为什么需要替代XMLHttpRequest

看了前面的例子,你可能会问,为什么不直接使用那些现有的XMLHttpRequest包装器呢? 原因在于Fetch API不仅仅为你提供了一个fetch()方法。

对于传统的XMLHttpRequest而言,你必须使用它的一个实例来执行请求和检索返回的响应。 但是通过Fetch API,我们还能够明确的配置请求对象。

你可以通过Request构造器函数创建一个新的请求对象,这也是建议标准的一部分。 第一个参数是请求的URL,第二个参数是一个选项对象,用于配置请求。请求对象一旦创建了, 你便可以将所创建的对象传递给fetch()方法,用于替代默认的URL字符串。示例代码如下:

var req = new Request(URL, {method: 'GET', cache: 'reload'});
fetch(req).then(function(response) {return response.json();
}).then(function(json) {insertPhotos(json);
});

上面的代码中我们指明了请求使用的方法为GET,并且指定不缓存响应的结果。

有关Request对象的另一件更酷的事在于,你还可以基于原有的对象创建一个新的对象。 新的请求和旧的并没有什么不同,但你可以通过稍微调整配置对象,将其用于不同的场景。 例如,你可以基于原有的GET请求创建一个POST请求,它们具有相同的请求源。代码如下:

// 基于req对象创建新的postReq对象
var postReq = new Request(req, {method: 'POST'});

每个Request对象都有一个header属性,在Fetch API中它对应了一个Headers对象。 通过Headers对象,你能够修改请求头。不仅如此,对于返回的响应,你还能轻松的返回响应头中的各个属性。 但是需要注意的是,响应头是只读的。

var headers = new Headers();
headers.append('Accept', 'application/json');
var request = new Request(URL, {headers: headers});fetch(request).then(function(response) {console.log(response.headers);
});

在上面的代码中,你可以通过Headers构造器来获取这个对象,用于为新的Request对象配置请求头。

相似的,你可以创建一个Response对象:

function responseDemo() {var headers = new Headers({'Content-Type': 'application/json','Cache-Control': 'max-age=3600'});var response = new Response(JSON.stringify({photos: {photo: []}}),{status: 200, headers: headers});response.json().then(function(json) {insertPhotos(json);});
}

RequestResponse都完全遵循HTTP标准。如果你曾经使用过某种服务器端语言,你应该对它们很熟悉。 但是对于浏览器而言创建HTTP响应的要点是什么?总之,你不能将它发送给其他人。但是, 你可以通过Service Worker API将响应发送给你自己。 Service Worker允许通过截取来自浏览器的请求头和提供本地构造的响应头来替换来自服务器的响应头的方式来构建离线应用。 你需要注意的是,在本文写作的时候Service Worker仍然是实验性的,并且仍处在不断变化之中。

Fetch API面临的阻力

Fetch API从提出到实现一直存在着争议,由于一直现存的历史原因(例如HTML5的拖拽API被认为太过稀疏平常,Web Components标准被指意义不大)。 因此重新设计一个新的API来替代久经沙场历练的XMLHttpRequest就变得阻力重重。

其中一种反对观点认为,Promises缺少了一些重要的XMLHttpRequest的使用场景。例如, 使用标准的ES6 Promise你无法收集进入信息或中断请求。而Fetch的狂热开发者更是试图提供Promise API的扩展用于取消一个Promise。 这个提议有点自挖墙角的意思,因为将这将让Promise变得不符合标准。但这个提议或许会导致未来出现一个可取消的Promise标准。 但另一方面,使用XMLHttpRequest你可以模拟进度(监听progress事件),也可以取消请求(使用abort()方法)。 但是,如果有必要你也可以使用Promise来包裹它。

另一种反对观点认为,Web平台需要的是更多底层的API,而不是高层的API。对此的回答恰恰是, Fetch API足够底层,因为当前的WHATWG标准定义了XMLHttpRequest.send()方法其实等同于fetch的Requset对象。 Fetch中的Response.body实现了getReader()方法用于渐增的读取原始字节流。 例如,如果照片列表过大而放不进内存的话,你可以使用下面的方法来处理:

function streamingDemo() {var req = new Request(URL, {method: 'GET', cache: 'reload'});fetch(req).then(function(response) {var reader = response.body.getReader();return reader.read();}).then(function(result, done) {if (!done) {// do something with each chunk}});
}

在上面的代码中处理器函数一块一块的接收响应体,而不是一次性的。当数据全部被读完后会将done标记设置为true。 在这种方式下,每次你只需要处理一个chunk,而不是一次性的处理整个响应体。

不幸的是,对于Stream API而言,这仍然还处于早期阶段,这种方式下,如果你需要解析JSON, 你仍然需要从头实现很多的工作。

浏览器支持

Fetch Support

Fetch API

目前Chrome 42+, Opera 29+, 和Firefox 39+都支持Fetch。微软也考虑在未来的版本中支持Fetch。 讽刺的是,当IE浏览器终于微响应实现了progress事件的时候,XMLHttpRequest也走到了尽头。 目前,如果你需要支持IE的话,你需要使用一个polyfill库。

转自:http://www.open-open.com/lib/view/open1452486942714.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499941.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[设计模式] ------ 策略模式

策略模式 它定义了算法家族,分别封装起来,让他们直接可以互相替换,此模式让算法的变化,不会影响到使用算法的客户 其实很简单,可能很多人都用到了,只不过还不知道这就是策略模式而已。 比如定义一个接口A…

OC语法简化

很多刚从其他编程语言转到Objective-C的同学看到长长的函数名会感到崩溃,这种语法让消息的传递像一个英语句子,大大增强了可读性。比如你想初始化一个浮点数,需要这么写: NSNumber value [NSNumber numberWithFloat:123.45f];从这…

[设计模式] ------ 简单工厂模式

简单工厂模式 不同类型下创建对应的不同的对象,得到不同的结果,就叫简单生产模式 比如 定义一个接口,叫A,里面有方法a,返回int类型 类B1实现A接口,也实现a方法,里面做的是加法运算 类B2实现…

Podfile语法

一、Podfile Podfile文件详细描述了一个或多个工程中targets的依赖关系。Podfile会默认创建一个隐式的目标链接到工程中用户的第一个target,名称为“default”。 一个Podfile可以非常简单: pod AFNetworking, ~> 1.0 也可以配置的复杂一点,如下: source https:/…

[设计模式] ------ 模板模式

模板模式 模板模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤 一般是定义一个抽象类,有抽象方法,有骨架方法&a…

获取本地沙盒文件的MIMEType

通过发送一个基于本地文件的URL请求,从响应对象中获取MIMEType值。代码如下:NSString *path [[NSBundle mainBundle] pathForResource:"测试文件"ofType:"pdf"]; //创建本地文件URL NSURL *url [NSURL fileURLWithPath:path]; //创…

第19章总结

一.Java绘图类 1.Graphics类 Graphics类是所有图形上下文的抽象基类,它允许应用程序在组件以及闭屏图像上进行绘制。Graphics类封装了Java支持的基本绘图操作所需的状态信息,主要包括颜色、字体、画笔、文本、图像等。 2.Graphics2D类 Graphics2…

如何写一个数据库中间件以及需要准备的知识储备

什么是数据库中间件 1.透明化使用方无感知,或者尽量少感知。通过现有的接入端接入已有服务 2.增量服务不改变数据库本身功能的前提下,提供额外的功能与服务一个原则不破坏原有逻辑,并且让用户基于之前的经验可以快速上手接入端协议的选择 1.…

HTTP断点续传

一、概述所谓断点续传,其实只是指下载,也就是要从文件已经下载的地方开始继续下载。在以前版本的HTTP协议是不支持断点的,HTTP/1.1开始就支持了。一般断点下载时才用到Range和Content-Range实体头。HTTP协议本身不支持断点上传,需…

RSA公钥文件(PEM)解析

公钥语法为: RSAPublicKey :: SEQUENCE { modulus INTEGER, //RSA合数模n publicExponent INTEGER //RSA公开幂e } 说明: 1.此语法中的modulus和publicExponent,提取自对应私钥中的同名域值。 2.PKCS1和PKCS8的公钥文件是一样的&#xff…

[spring boot] ------ 总结1

spring boot 设计目的:简化spring应用的初始搭建以及开发过程 spring环境的微服务:对原有技术的封装(spring springMVC) 简化开发,提高开发效率(原ssm--->spring boot mybatis) 自动配置&…

RSA私钥文件(PEM-PKCS#1)解析

在PKCS#1 RSA算法标准中定义RSA私钥语法 RSAPrivateKey :: SEQUENCE { version Version, //版本 modulus INTEGER, // RSA合数模 n publicExponent INTEGER, //RSA公开幂 e privateExponent INTEGER, //RSA私有幂 d prime1 INTEGER, //n的素数因子p prime2 INTEGER, //n的…

Spring的@Configuration使用cglib代理的效果和我自己写的简单实现

下面的代码,照着复制就能跑起来 今天看了下Spring的Configuration,即java类配置bean,(这个spring3的新功能,虽然现在已经spring5了,但是这种配置bean的方式也是比较火的) 做了如下测试,发现一个…

Xcode中StaticLibrary和Framework的共同点和区别

一、共同点:两者其实都是静态库。二、区别1.承载的内容范畴:(1)StaticLibrary的产出物只是一个.a文件,为二进制执行文件。分享给别人的时候,头文件、静态资源文件需要另外提供。(2)Framework为一站式分享方案,其实是一…

[分布式] ------ 全局唯一id生成之雪花算法(Twitter_Snowflake)

雪花算法(Twitter_Snowflake) 我们知道,分布式全局唯一id的生成,一般是以下几种: 基于雪花算法生成基于数据库基于redis基于zookeeper 本文说下雪花算法,后面附源码以及测试代码。 如下图: …

非对称加解密交互故事

1.鲍勃有两把钥匙,一把是公钥,另一把是私钥。 2.鲍勃把公钥送给他的朋友们—-帕蒂、道格、苏珊—-每人一把。 3.苏珊要给鲍勃写一封保密的信。她写完后用鲍勃的公钥加密,就可以达到保密的效果 4.鲍勃收信后,用私钥解密&#xff0…

2019年规划

2019年规划,到2019-12-31检查: 1.至少读5本与工作无关的书(平均两个月1本),每本都产出读后感 1.1 《重构 改善代码既有设计》,2月19日~3月5日,刚好两周读完,产出两篇总结&#xff0…

RSA私钥文件(PEM-PKCS#8)解析

***此文仅针对没有执行加密的PKCS#8私钥文件***一、实例解析PKCS#8格式使用的是ASN.1结构,首先我们对一个没有执行加密的PKCS#8格式私钥文件进行一下解析,方便我们下面分析其结构。命令:openssl asn1parse -i -in privatekey.pem结果如下&…

分布式和集群的区别

分布式和集群的区别 分布式是多个不同功能的机器共同完成一件事情 集群是多个相同功能的机器完成的是相同的事情 分布式是为了分担压力 集群是为了稳定性和高可用 举个例子: 一个厨师开了一个饭店,他要负责做饭和卖饭,他的压力就比较大&am…

Sqlite3中replace语句用法详解

在本例中使用如下数据库表: (图 1) 该表的表名为student, 存储学生信息。 所有字段的数据类型都是TEXT 。 其中id和name作为复合主键。 email字段加上了唯一约束。建表语句如下: CREATE TABLE IF NOT EXISTS student …