使用fetch在JavaScript中发送HTTP请求

Using fetch to Send HTTP Requests in JavaScript

介绍

JavaScript的Fetch API允许我们发送HTTP请求。 自从ECMAScript 2015(通常称为ES6)被引入并使用Promises以来,它一直是JavaScript的标准部分。

本文将首先向您展示在开发Fetch API之前如何使用原始JavaScript发出请求。 然后,我们将指导您如何使用Fetch API,重点介绍与其他方法相比有何改进。

建立

本文着眼于使用Fetch API在浏览器中发出HTTP请求。 因此,我们需要设置一个我们的浏览器可以显示的HTML页面。 在您的工作区中,首先创建一个index.html文件。

index.html文件将在本文中使用。 HTML页面没有文本内容,它将仅用于加载JS文件,因此我们可以在浏览器的控制台中查看请求和响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>JavaScript HTTP Requests</title>
</head>

<body>
    <script src="./xhr.js"></script>
</body>

</html>

当我们学习新主题时,我们将更改script标记,但是HTML的其余部分将保持不变。

您还希望打开浏览器控制台,以便我们可以查看HTTP请求的结果。 通常,通过右键单击网页并选择"检查"来完成此操作。 在Chrome上看起来像这样:

The

现在,让我们选择"控制台"选项卡,以便我们可以看到我们的JavaScript记录的所有输出:

The

你们都准备好了! 让我们开始使用JavaScript可能的第一种方法-XMLHttpRequest发送HTTP请求。

使用XMLHttpRequest的请求

在Fetch API存在之前,所有JavaScript请求都是使用XMLHttpRequest(或XHR)对象完成的。 尽管其名称,此对象仍可以从服务器检索任何格式的数据。 它不仅限于XML。

让我们在浏览器中处理XHR请求。 在index.html文件所在的文件夹中,创建一个新的xhr.js文件。

这个新的JavaScript文件将创建一个XHR对象,并将GET请求发送到JSON API。 然后,我们将在控制台中记录请求的结果。 在您的xhr.js文件中,输入以下内容:

1
2
3
4
5
6
7
let xhr = new XMLHttpRequest();
xhr.open('get', 'https://jsonplaceholder.typicode.com/posts/1');
xhr.send();

xhr.onload = function() {
    console.log(xhr.response);
};

在第一行中,我们创建了一个新的XMLHttpRequest对象。 然后,我们使用open()方法创建一个新的HTTP请求。 open()的第一个参数是请求的HTTP方法-在这种情况下,我们正在发送GET请求。 第二个参数是带有所需服务器资源的URL。 然后,我们使用send()方法调度请求。

XHR成功从网络获取数据时,它将发送加载事件。 要在加载数据后对其进行处理,我们将一个函数设置为XHR对象的onload属性。 在这种情况下,我们只需将响应记录到控制台即可。

现在,在开发人员控制台中,您应该看到以下内容。

JSON output of the XHR request for blog posts

XMLHttpRequest发出API请求真是好极了!

尽管可维护,但它处理异步数据的方式与现代JavaScript中使用的组织化和标准化Promises截然不同。 我们可以使用Fetch API维护更简单的代码。

提取API

Fetch API是基于诺言的API,用于发出HTTP请求,类似于我们使用XMLHttpRequest所做的事情。 与XMLHttpRequest不同,在使用Fetch API时,我们不必创建新对象。 浏览器带有全局fetch()函数,我们可以使用该函数进行请求。

让我们看看如何使用此API通过Internet发出HTTP请求。

通过提取发送请求

Fetch API可以发出GETPOSTPUTPATCHDELETE和其他类型的HTTP请求。 我们将重点介绍HTTP请求中使用的两种最常用的方法:GETPOST

GET请求

让我们像之前使用XMLHttpRequest一样,使用Fetch API向https://jsonplaceholder.typicode.com/posts/1发出GET请求。

在您的index.html文件中,更改script标记以引用一个新的JavaScript文件:

1
<script src="./fetchGet.js"></script>

现在,在同一工作区中创建新的fetchGet.js文件。 我们将发送GET请求,并将输出再次记录到控制台。 在fetchGet.js中输入以下代码:

1
2
3
fetch('https://jsonplaceholder.typicode.com/posts/1')
    .then(response => response.json())
    .then(json => console.log(json));

在第一行中,我们使用全局fetch()函数将GET请求发送到我们的API。 fetch()的参数是带有服务器端资源的URL。

然后,我们将诺言与then()方法链接,该方法捕获response参数中的HTTP响应并调用其json()方法。 json()方法将响应主体解析为JSON对象。 但是,它将其作为一种承诺返回。

这就是为什么再次使用then()链接另一个诺言的原因,该诺言将已解析的JSON记录到控制台。

如果需要,重新加载index.html,这样您就可以看到以下输出:

JSON output of the fetch request for blog posts

注意:输出看起来与使用XMLHttpRequest发出GET请求时得到的输出不同。 这是因为XMLHttpRequest将HTTP响应数据作为字符串返回,而我们将数据解析为JSON对象。 虽然返回的格式不同,但是它们的内容相同。

让我们看看如何使用fetch()POST请求中发送数据。

POST请求

我们可以通过添加fetch()来上传数据,方法是添加一个JavaScript对象作为其第二个参数,并带有发送HTTP请求所需的信息。

让我们使用fetch()POST请求中的JSON数据上传到模拟API。 在您的index.html文件中,更改script标记以引用一个新的JavaScript文件:

1
<script src="./fetchPost.js"></script>

现在,在工作空间中创建fetchPost.js,以便我们向API发出POST请求,该请求将以JSON对象的形式上传新的待办事项。 在fetchPost.js中键入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const todo = {
    title: 'Some really important work to finish'
};

fetch('https://jsonplaceholder.typicode.com/todos', {
        method: 'POST',
        body: JSON.stringify(todo),
        headers: {
            'Content-type': 'application/json; charset=UTF-8'
        }
    })
    .then(response => response.json())
    .then(json => {
        console.log(json);
    });

我们要做的第一件事是创建一个todo对象,其中包含我们要发送到API的数据。

GET请求一样,我们通过提供我们要访问的API的URL来使用fetch()。 但是,这次我们有一个对象作为fetch()的第二个参数,具有以下属性:

  • method:一个字符串,用于指定要在请求中使用的HTTP方法

  • body:包含我们要在请求中提供给服务器的任何数据的字符串

  • headers:一个允许我们添加希望HTTP请求包含的标头的对象

  • GET请求一样,我们将服务器的响应作为JSON处理并将其记录到开发人员控制台。 重新加载index.html应该会向我们显示以下控制台输出:

    JSON output of the fetch POST request to add a new

    使用fetch()通过POST请求上传数据真是太好了!

    现在,我们已经掌握了使用Fetch API发出各种HTTP请求的方法,让我们看看如何处理不同的HTTP响应。

    使用提取处理响应

    到目前为止,我们一直在将响应数据解析为JSON。 尽管此方法适用于示例中使用的API,但其他响应可能返回不同类型的非JSON数据。

    成功的fetch()请求后返回的HTTP响应对象可以解析为各种格式。 除了json()方法,我们还可以使用以下方法:

  • text():以字符串数据形式返回响应

  • blob():以blob对象形式返回响应(二进制数据及其编码)

  • formData():将响应作为FormData对象返回(该对象存储字符串数据的键值对)

  • arrayBuffer():将响应作为ArrayBuffer返回(二进制数据的低级表示)

  • json()方法一样,这些函数返回带有内容的promise。 因此,它们都必须与then()函数链接在一起,以便可以处理内容。

    这些函数用于处理返回数据的成功HTTP响应。 现在让我们看一下如何使用Fetch API处理错误。

    处理HTTP错误

    与任何其他promise一样,fetch()错误在promise链末尾的catch()方法中处理。 但是,仅当fetch()无法发送请求时才使用catch()函数。 这通常意味着存在网络错误。

    如果我们尝试访问一个不存在的URL,并且服务器返回404,则它不会被catch()方法捕获,因为404是有效的HTTP响应状态。

    因此,在使用Fetch API处理错误时,我们需要做两件事:

  • 在Promise链的末尾包含catch()子句,以拾取任何网络错误

  • 检查响应的HTTP状态代码以查看是否成功。

  • 让我们做另一个示例,尝试获取不存在的URL。

    使用我们的GET请求示例,我们可以像这样使用catch()

    1
    2
    3
    4
    fetch('https://jsonplaceholder.typicode.com/posts/1')
        .then(response => response.json())
        .then(json => console.log(json))
        .catch(err => console.error(err));

    但是,仅当无法发送fetch()请求时才使用catch()函数。 在您的index.html文件中,更改脚本标签以引用新的JavaScript文件:

    1
    <script src="./fetchError.js"></script>

    现在在您的工作区中创建一个新的fetchError.js文件。 输入以下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    fetch("https://jsonplaceholder.typicode.com/notreal/")
        .then(response => {
            if (!response.ok) {
                throw new Error("Could not reach website.");
            }
            return response.json();
        })
        .then(json => console.log(json))
        .catch(err => console.error(err));

    首先,向该API上不存在的URL发送GET请求。 请注意第一个then()函数的更改,该函数将响应主体解析为JSON:

    1
    2
    3
    if (!response.ok) {
        throw new Error("Could not reach website.");
    }

    我们检查ok属性,它是布尔值。 如果响应的HTTP状态代码在200-299之间,则为true。 通过使用not运算符(!),我们可以捕获服务器返回HTTP错误的情况。 如果确实收到HTTP错误,则会抛出一个自定义错误,该错误将终止fetch()承诺链。

    如果没有收到HTTP错误,我们将像以前一样返回JSON响应作为承诺。

    在Promise链的末尾,我们有一个catch()函数,该函数只是将错误记录到控制台。

    如果重新加载index.html页面,则应该看到以下控制台输出:

    Error output trying to reach a fake URL

    做得好,您介绍了Fetch API的基础知识。

    结论

    Fetch API提供了一种基于承诺的方式,以JavaScript发送HTTP请求。 由于它是基于承诺的,因此开发人员将其视为XMLHttpRequest的更干净的替代品。

    使用fetch()函数,我们可以向不同的URL发出GETPOST请求。 我们可以配置fetch()请求以使用我们要使用的任何HTTP方法。

    fetch()函数还提供了一个response对象,该对象可以解析为各种格式。 其中包括JSON,文本和字节等。

    我们还看到了使用fetch()发出请求时如何处理错误。 除了将catch()方法放在承诺链的末尾以拾取网络错误之外,我们还应该在解析其数据之前检查收到的HTTP响应的状态代码。

    Fetch API使外部API调用可管理,而无需使用外部库。 您打算使用fetch()-访问哪些API