likes
comments
collection
share

用async/await使用Fetch函数的教程

作者站长头像
站长
· 阅读数 82

如何用async/await使用Fetch

Fetch API是在Web应用程序中进行网络的默认工具。虽然fetch() 一般来说很容易使用,但也有一些细微差别需要注意。

在这篇文章中,你会发现如何使用fetch()async/await 语法的常见场景。你将了解如何获取数据、处理获取错误、取消获取请求,以及更多。

目录

1.fetch() 的介绍

Fetch API在网络上访问资源。你可以进行HTTP请求(使用GET,POST 和其他方法),下载和上传文件。

要开始一个请求,请调用特殊函数fetch()

  const response = await fetch(resource[, options]);

它接受两个参数:

  • resource: URL字符串,或一个Request对象
  • options method, , ,headers body credentials属性的配置对象。

fetch() 开始一个请求并返回一个承诺。当请求完成时,该承诺被Response对象解析。如果由于某些网络问题导致请求失败,则拒绝该承诺。

async/await 语法非常适用于fetch() ,因为它简化了承诺的工作。

例如,让我们做一个请求来获取一些电影。

async function fetchMovies() {
  const response = await fetch('/movies');
  // waits until the request completes...
  console.log(response);
}

fetchMovies() 是一个异步函数,因为它被标记为async 关键字。

await fetch('/movies') 开始一个HTTP请求到'/movies' URL。因为await 关键字的存在,异步函数被暂停,直到请求完成。

当请求完成后,response ,并分配给请求的响应对象。让我们在下一节看看如何从响应中提取有用的数据,如JSON或纯文本。

2.取出JSON

response 对象,由await fetch() 返回,是一个通用的占位符,用于多种数据格式。

例如,你可以从一个获取响应中提取JSON对象。

async function fetchMoviesJSON() {
  const response = await fetch('/movies');
  const movies = await response.json();
  return movies;
}
fetchMoviesJSON().then(movies => {
  movies; // fetched movies
});

response.json() 是Response对象的一个方法,让你从响应中提取一个JSON对象。该方法返回一个承诺,所以你必须等待JSON: 。await response.json()

响应对象提供了很多有用的方法(都返回承诺):

  • response.json() 返回一个解析为JSON对象的承诺
  • response.text() 返回一个解析为原始文本的承诺
  • response.formData() 返回一个解析为FormData的承诺
  • response.blob() 返回一个解析为Blob(原始数据的类文件对象)的承诺
  • response.arrayBuffer()() 返回一个解析为ArryBuffer(原始的通用二进制数据)的承诺。

3.处理获取错误

当我在熟悉fetch() ,我很惊讶,当服务器返回一个糟糕的HTTP状态时,fetch() 并没有抛出一个错误,例如客户端(400–499)或服务器错误(500–599)。

例如,让我们访问服务器上一个不存在的页面'/oops' 。正如预期的那样,这种请求以404 响应状态结束。

async function fetchMovies404() {
  const response = await fetch('/oops');
  
  response.ok;     // => false
  response.status; // => 404
  const text = await response.text();
  return text;
}
fetchMovies404().then(text => {
  text; // => 'Page not found'
});

当获取URL'/oops' 时,服务器响应的状态是404 ,文本是'Page not found' 。令人惊讶的是,fetch() 并没有因为缺少URL而产生错误,而是认为这是一个完成的HTTP请求。

fetch() 只有在无法提出请求或无法检索到响应时才会拒绝。这可能是由于网络问题而发生的:没有网络连接,找不到主机,服务器没有响应。

幸运的是,response.ok 属性可以让你区分好的和坏的HTTP响应状态。只有当响应的状态是200-299 ,该属性才会被设置为true

在上面的例子中,response.ok 属性是false ,因为响应的状态是404

如果你想在一个坏的HTTP状态下抛出一个错误(在200-299 范围之外),检查response.ok 属性的值并手动抛出一个错误。

async function fetchMoviesBadStatus() {
  const response = await fetch('/oops');
  if (!response.ok) {
    const message = `An error has occured: ${response.status}`;
    throw new Error(message);
  }
  const movies = await response.json();
  return movies;
}
fetchMoviesBadStatus().catch(error => {
  error.message; // 'An error has occurred: 404'
});

4.取消一个获取请求

不幸的是,fetch() API本身不允许在开始后取消一个获取请求。要取消一个获取请求,你需要一个额外的工具AbortController

连接fetch()AbortController 需要 3 个步骤。

// Step 1: instantiate the abort controller
const controller = new AbortController();
// Step 2: make the fetch() aware of controller.signal
fetch(..., { signal: controller.signal });
// Step 3: call to cancel the request
controller.abort();

A) 在开始请求之前,创建一个中止控制器实例:controller = new AbortController()

B) 当正确启动请求时,使用fetch(url, { signal: controller.signal }) 的选项参数,并将signal 属性设置为controller.signal

C)最后,如果你需要取消请求,只需调用controller.abort() 方法。

例如,让我们实现2个按钮来控制一个获取请求。点击按钮Fetch movies开始一个fetch() 请求,而点击Cancel fetch中止正在进行的请求。

let controller = null;
fetchMoviesButton.addEventListener('click', async () => {
  controller = new AbortController();
  try {
    const response = await fetch('/movies', { 
      signal: controller.signal 
    });
  } catch (error) {
    console.log('Fetch error: ', error);
  }
  controller = null;
});
cancelFetchButton.addEventListener('click', () => {
  if (controller) {
    controller.abort();
  }
});

打开演示。点击Fetch movies来启动请求,然后马上点击Cancel fetch来取消请求。这使得活动的请求被取消:await fetch() 被拒绝,抛出一个中止错误。然后catch 块捕捉到中止错误。

终止控制器实例是不可重复使用的。每次你启动一个fetch() 请求,你必须为每个请求创建一个新的中止控制器实例。

顺便提一下,如果你想对fetch() 请求进行超时处理,请关注我的文章《如何对fetch()请求进行超时处理》。

5.平行获取请求

要执行平行的获取请求,请使用Promise.all()辅助函数。

让我们开始2个平行请求来获取电影和类别。

async function fetchMoviesAndCategories() {
  const [moviesResponse, categoriesResponse] = await Promise.all([
    fetch('/movies'),
    fetch('/categories')
  ]);
  const movies = await moviesResponse.json();
  const categories = await categoriesResponse.json();
  return [movies, categories];
}
fetchMoviesAndCategories().then(([movies, categories]) => {
  movies;     // fetched movies
  categories; // fetched categories
}).catch(error => {
  // /movies or /categories request failed
});

await Promise.all([...]) 开始平行地获取请求,并等待所有的请求被解决。

如果有任何请求失败,那么整个并行请求就会立即被拒绝,并出现失败的请求错误。

转载自:https://juejin.cn/post/7126441823584649224
评论
请登录