Fetch API简介

在本文中,我们将学习新的Fetch API的外观,解决的问题以及使用fetch()函数在网页内检索远程数据的最实用方法。

多年来, XMLHttpRequest一直是Web开发人员值得信赖的伙伴。 无论是直接还是在幕后, XMLHttpRequest都启用了Ajax和从Gmail到Facebook的全新的交互式体验。

但是, Fetch API逐渐取代了XMLHttpRequest 。 两者都可以用于发出网络请求,但是Fetch API是基于Promise的,它提供了一种更简洁,更简洁的语法,并使您远离回调地狱

提取API

Fetch API提供了在window对象上定义的fetch()方法,您可以使用该方法执行请求。 此方法返回一个Promise ,可用于检索请求的响应。

fetch方法只有一个必填参数,它是您希望获取的资源的URL。 一个非常基本的示例如下所示。 这从r / javascript上Reddit上获取了前五篇文章:

fetch('https://www.reddit.com/r/javascript/top/.json?limit=5')
.then(res => console.log(res));

如果在浏览器的控制台中检查响应,则应该看到具有以下属性的Response对象:

{
  body: ReadableStream
  bodyUsed: false
  headers: Headers {}
  ok: true
  redirected: false
  status: 200
  statusText: ""
  type: "cors"
  url: "https://www.reddit.com/top/.json?count=5"
}

请求似乎成功了,但我们的前五名职位在哪里? 让我们找出答案。

加载JSON

在请求完成之前,我们不能阻止用户界面等待。 这就是为什么fetch()返回Promise的原因,该对象表示将来的结果。 在上面的示例中,我们使用then方法来等待服务器的响应并将其记录到控制台。

现在,让我们看看一旦请求完成,我们如何从该响应中提取JSON有效负载:

fetch('https://www.reddit.com/r/javascript/top/.json?limit=5')
.then(res => res.json())
.then(json => console.log(json));

我们通过调用fetch()启动请求。 兑现承诺后,它将返回一个Response对象,该对象公开一个json方法。 在第一个then()我们可以调用此json方法以将响应主体作为JSON返回。

但是, json方法还返回一个promise,这意味着我们需要在JSON响应记录到控制台之前链接到另一个then()

为什么json()返回诺言? 因为HTTP允许您逐块将内容流式传输到客户端,所以即使浏览器收到服务器的响应,内容主体也可能还不存在!

异步…等待

.then()语法不错,但是在2018年处理承诺的一种更简洁的方法是使用async … await -ES2017引入的新语法。 使用async Ú await意味着我们可以将一个函数标记为async ,然后使用await关键字await诺言完成,然后作为常规对象访问结果。 所有现代浏览器(不是IE或Opera Mini)和Node.js 7.6+都支持异步功能。

这是上面使用async … await示例的样子(略有扩展):

async function fetchTopFive(sub) {
  const URL = `https://www.reddit.com/r/${sub}/top/.json?limit=5`;
  const fetchResult = fetch(URL)
  const response = await fetchResult;
  const jsonData = await response.json();
  console.log(jsonData);
}

fetchTopFive('javascript');

没有太大变化。 除了我们创建了一个async函数(向其传递subreddit的名称)外,我们现在还在等待调用fetch()的结果,然后再次使用await从响应中检索JSON。

这是基本的工作流程,但是涉及远程服务的事情并不总是能顺利进行。

处理错误

假设我们向服务器请求不存在的资源或需要授权的资源。 使用fetch() ,您必须在正常流中处理应用程序级错误,例如404响应。 如前所述, fetch()返回带有ok属性的Response对象。 如果response.oktrue ,则响应状态码位于200范围内:

async function fetchTopFive(sub) {
  const URL = `http://httpstat.us/404`; // Will return a 404
  const fetchResult = fetch(URL)
  const response = await fetchResult;
  if (response.ok) {
    const jsonData = await response.json();
    console.log(jsonData);
  } else {
    throw Error(response.statusText);
  }
}

fetchTopFive('javascript');

来自服务器的响应代码的含义因API而异,并且通常仅检查response.ok可能不够。 例如,即使您的API密钥无效,某些API也会返回200响应。 请务必阅读API文档!

要处理网络故障,请使用try … catch块:

async function fetchTopFive(sub) {
  const URL = `https://www.reddit.com/r/${sub}/top/.json?limit=5`;
  try {
    const fetchResult = fetch(URL)
    const response = await fetchResult;
    const jsonData = await response.json();
    console.log(jsonData);
  } catch(e){
    throw Error(e);
  }
}

fetchTopFive('javvascript'); // Notice the incorrect spelling

catch块中的代码仅在发生网络错误时运行。

您已经了解了发出请求和阅读回复的基础知识。 现在,让我们进一步自定义请求。

更改请求方法和标题

查看上面的示例,您可能想知道为什么不能仅使用现有的XMLHttpRequest包装器之一 。 原因是fetch API提供的不仅仅是fetch()方法。

虽然必须使用XMLHttpRequest的相同实例来执行请求并检索响应,但fetch API允许您显式配置请求对象。

例如,如果您需要更改fetch()发出请求的方式(例如,配置请求方法),则可以将Request对象传递给fetch()函数。 Request构造函数的第一个参数是请求URL,第二个参数是配置请求的选项对象:

async function fetchTopFive(sub) {
  const URL = `https://www.reddit.com/r/${sub}/top/.json?limit=5`;
  try {
    const fetchResult = fetch(
      new Request(URL, { method: 'GET', cache: 'reload' })
    );
    const response = await fetchResult;
    const jsonData = await response.json();
    console.log(jsonData);
  } catch(e){
    throw Error(e);
  }
}

fetchTopFive('javascript');

在这里,我们指定了request方法,并要求它不要缓存响应。

您可以通过将Headers对象分配给请求headers字段来更改请求标headers 。 以下是仅使用'Accept'标头要求JSON内容的方法:

const headers = new Headers();
headers.append('Accept', 'application/json');
const request = new Request(URL, { method: 'GET', cache: 'reload', headers: headers });

您可以从旧请求中创建一个新请求,以针对不同的用例进行调整。 例如,您可以创建从GET请求到同一资源的POST请求。 这是一个例子:

const postReq = new Request(request, { method: 'POST' });

您还可以访问响应头,但请记住,它们是只读值。

fetch(request).then(response => console.log(response.headers));

RequestResponse严格遵循HTTP规范; 如果您曾经使用服务器端语言,则应该识别它们。 如果您想了解更多信息,可以在MDNFetch API页面上阅读有关它们的全部信息。

汇集全部

为了使本文更完整,这是一个可运行的示例,该示例演示如何从特定的subreddit中获取前五个帖子,并在列表中显示其详细信息。

请参阅CodePen上的SitePoint@SitePoint )提供的Pen Fetch API演示

尝试输入一些子索引(例如“ javascript”,“ node”,“ linux”,“ lolcats”)以及一些不存在的子索引。

从这往哪儿走

在本文中,您已经看到了新的Fetch API的外观以及解决的问题。 我已经演示了如何使用fetch()方法检索远程数据,如何处理错误以及如何创建Request对象来控制request方法和标头。

如下图所示,对fetch()支持很好。 如果您需要支持较旧的浏览器,可以使用polyfill

我可以使用提取吗? 来自caniuse.com在主要浏览器中支持提取功能的数据。

因此,下次您到达像jQuery这样的库来发出Ajax请求时,请花点时间考虑是否可以使用本机浏览器方法。

From: https://www.sitepoint.com/introduction-to-the-fetch-api/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值