Skip to content

Latest commit

 

History

History
85 lines (69 loc) · 4.75 KB

4.1.md

File metadata and controls

85 lines (69 loc) · 4.75 KB

4.1 Fetch API

作为 Web 开发者,为了异步更新应用,我们通常需要从服务器获取数据的能力。传统上,这个数据是通过使用 JavaScript 和 XMLHttpRequest 对象来获取的。也被称为 AJAX,它是开发者梦寐以求的,因为它允许你更新网页,而不必通过在后台进行 HTTP 请求来重新加载页面。在我们的示例应用 Progressive Times 中,我们也会异步获取新闻文章列表。

如果你曾经实现过复杂的逻辑来从服务器获取数据,使用 XMLHttpRequest 对象来编写代码会相当棘手。随着开始添加越来越多的逻辑和回调函数,代码很快就变得一团糟。

代码清单 4.1
var request;
if (window.XMLHttpRequest) {
  request = new XMLHttpRequest();
} else if (window.ActiveXObject) {
  try {
    request = new ActiveXObject('Msxml2.XMLHTTP');
  } catch (e) {
    try {
      request = new ActiveXObject('Microsoft.XMLHTTP');
    } catch (e) {}
  }
}
request.onreadystatechange = function () {
  if (this.readyState == 4 && this.status == 200) {
    doSomething(this.responseText);
  }
};
// 打开,发送
request.open('GET', '/some/url', true);
request.send();

清单4.1中的代码看上去有些多,只是简单地发起一个 HTTP 请求而已!有趣的是,XMLHttpRequest 对象最初是由 Microsoft Exchange Server 的 Outlook Web Access 的开发人员创建的。经过一系列的置换之后,它最终成为如今在 JavaScript 中发起 HTTP 请求的标准。上面的示例完成了它的目的,但代码本身并不够简洁。上面的代码还有另外一个问题,你的逻辑越复杂,代码就越复杂。过去,有许多库和技术可以使这种代码更简单,更易于阅读,诸如 jQuery 和 Zepto 等流行库,它们具有更简洁的 API 。

幸运的是,现代浏览器厂商都意识到这是需要改进的,这也正是 Fetch API 诞生的原因。Fetch API 是 Service Worker 全局作用域的一部分,它可以用来在任何 Service Worker 中发起 HTTP 请求。截止到目前为止,我们一直在 Service Worker 代码中使用 Fetch API,但我们还未曾深入研究它。我们来看几个代码示例,以便更好地理解 Fetch API 。

代码清单 4.2
fetch('/some/url', {           
  method: 'GET'
}).then(function (response) {  
  // 成功
}).catch(function (err) {      
  // 出问题了
});
  • ❶ 使用 GET 请求访问的 URL
  • ❷ 如果成功,则返回响应
  • ❸ 如果出问题了,我们可以做出相应的响应

清单4.2中的代码是 Fetch API 实际应用的基础示例。你可能还注意到了没有回调函数和事件,取而代之的是 then() 方法。这个方法是 ES6 中新功能 Promises 的一部分,目的是使我们的代码更具可读性、更便于开发者理解。Promise 代表异步操作的最终结果,我们不知道实际的结果值是什么,直到将来某个时刻操作完成。

上面的代码看起来很容易理解,但是使用 Fetch API 发起 POST 请求呢?

代码清单 4.3
fetch('/some/url', {                            
    method: 'POST',
    headers: {
      'auth': '1234'                            
    },
    body: JSON.stringify({                      
      name: 'dean',
      login: 'dean123',
    })
  })
  .then(function (data) {                       
    console.log('Request success: ', data);
  })
  .catch(function (error) {                     
    console.log('Request failure: ', error);
  });
  • ❶ 使用 POST 请求访问的 URL
  • ❷ 请求中包含的 headers
  • ❸ POST 请求的 body
  • ❹ 如果成功,则返回响应
  • ❺ 如果出问题了,我们可以做出相应的响应

假如说,你想要使用 POST 请求将某个用户详情发送到服务器。在上面的清单中,只需在 fetch 选项中将 method 更改为 POST 并添加 body 参数。使用 Promises 不仅可以使代码更整洁,而且还可以使用链式代码,以便在 fetch 请求之间共享逻辑。

目前所有支持 Service Workers 的浏览器中都可以使用 Fetch API ,但如果想在不支持的浏览器上使用的话,你可能要考虑使用 polyfill 。它只是一段代码,为你提供你所期望的现代浏览器功能。例如,如果最新版本的 IE 具有一些你所需要的功能,但旧版本中没有,polyfill 可以用来为老旧浏览器提供类似的功能。可以把它当作是 API 的包装,用来保持 API 完整可用。这有一个由 Github 团队编写的 polyfill (https://github.com/github/fetch),它会确保老旧浏览器能够使用 fetch API 发起请求。只需要将它放置在网页中,你便能够开始使用 fetch API 来编写代码。