Fetch是一种新的、基于promise的API,它允许我们在执行Ajax请求时不需要处理与XMLHttpRequest相关的所有麻烦。正如你将在这篇文章中看到的,Fetch非常容易使用,并且极大地简化了从API获取资源的过程。另外,所有的现代浏览器都支持它,因此Fetch使用起来非常简单。

Get请求

让我们通过从JSONPlaceholder API获取一些假数据来演示一个简单的GET请求:

  1. fetch('https://jsonplaceholder.typicode.com/users')
  2. .then(res => res.json())
  3. .then(res => res.map(user => user.username))
  4. .then(userNames => console.log(userNames));

输出将是这样的用户名数组:

  1. ["Bret", "Antonette", "Samantha", "Karianne", "Kamren", "Leopoldo_Corkery", "Elwyn.Skiles", "Maxime_Nienow", "Delphine", "Moriah.Stanton"]

如果我们期望得到一个JSON响应,我们首先需要调用json()方法将Response对象转换为可以与之交互的对象。如果我们期望得到XML响应,则可以使用text()。

Post, Put 以及 Delete 请求

要发出除GET以外的请求,可以将一个对象作为第二个参数传递给fetch调用,这个对象还需要包含头文件和请求正文:

  1. const myPost = {
  2. title: 'A post about true facts',
  3. body: '42',
  4. userId: 2
  5. }
  6. const options = {
  7. method: 'POST',
  8. body: JSON.stringify(myPost),
  9. headers: {
  10. 'Content-Type': 'application/json'
  11. }
  12. };
  13. fetch('https://jsonplaceholder.typicode.com/posts', options)
  14. .then(res => res.json())
  15. .then(res => console.log(res));

JSONPlaceholder会将发送的数据连同ID一起返回给我们:

  1. Object {
  2. body: 42,
  3. id: 101,
  4. title: "A post about true facts",
  5. userId: 2
  6. }

你可能有注意到,这个请求的主体需要字符串化。另外一些可以使用的fetch的方法有DELETEPUTHEADOPTIONS

错误处理

使用Fetch API处理错误时有一个陷阱(双关语😉):如果请求正确地到达端点并返回,则不会抛出任何错误。这意味着处理错误不能像在promise链的末尾链接catch方法那么简单。

幸运的是,来自fetch调用返回的响应对象具有ok属性,根据请求的成功情况,该属性将为true或false。当ok为false的时候你可以使用Promise.reject()

  1. fetch('https://jsonplaceholder.typicode.com/postsZZZ', options)
  2. .then(res => {
  3. if (res.ok) {
  4. return res.json();
  5. } else {
  6. return Promise.reject({ status: res.status, statusText: res.statusText });
  7. }
  8. })
  9. .then(res => console.log(res))
  10. .catch(err => console.log('Error, with message:', err.statusText));

在上述示例中,我们的promise将被拒绝,因为我们正在调用不存在的端点。链接的catch将会被调用并输出以下内容:

  1. "Error, with message: Not Found"

Fetch + Async/Await

由于Fetch是一个基于promise的API,使用异步函数是一个不错的选择,让你的代码更容易推理和同步查找。
例如,这里有一个async/await函数,它执行一个简单的GET请求,并从返回的JSON响应中提取用户名,然后在控制台输出结果:

  1. async function fetchUsers(endpoint) {
  2. const res = await fetch(endpoint);
  3. let data = await res.json();
  4. data = data.map(user => user.username);
  5. console.log(data);
  6. }
  7. fetchUsers('https://jsonplaceholder.typicode.com/users');

或者,可以从你的异步/等待函数返回一个promise,然后你就可以保持链接,然后在调用该函数后进行调用:

  1. async function fetchUsers(endpoint) {
  2. const res = await fetch(endpoint);
  3. const data = await res.json();
  4. return data;
  5. }
  6. fetchUsers('https://jsonplaceholder.typicode.com/users')
  7. .then(data => {
  8. console.log(data.map(user => user.username));
  9. });

调用json()会返回一个promise,因此在上面的示例中,当我们在async函数中返回数据时,我们返回了一个promise。

然后,如果响应的ok为false,那么你也可以抛出一个错误,并像往常一样在promise链中捕获错误:

  1. async function fetchUsers(endpoint) {
  2. const res = await fetch(endpoint);
  3. if (!res.ok) {
  4. throw new Error(res.status); // 404
  5. }
  6. const data = await res.json();
  7. return data;
  8. }
  9. fetchUsers('https://jsonplaceholder.typicode.com/usersZZZ')
  10. .then(data => {
  11. console.log(data.map(user => user.website));
  12. })
  13. .catch(err => console.log('Ooops, error', err.message));
  1. Ooops, error 404

Polyfills

如果你需要支持较旧的浏览器,例如Internet Explorer 11,则需要使用Github中的Fetch polyfill
如果需要在Node.js中使用Fetch,则两个最受欢迎的选择是isomorphic-fetchnode-fetch

原文地址:https://alligator.io/js/fetch-api