JavaScript Fetch API 入门
过去,有两种方式发出请求。一种是使用XMLHttpRequest
。另一种是使用 jQuery,即ajax()
方法。幸运的是,JavaScript 现在提供了第三种方式——Fetch API。在本教程中,您将学习 JavaScript Fetch API 入门所需的所有知识。
简要介绍
Fetch API 是 JavaScript 标准中新增的 API。它提供了一种更简单、更清晰的服务器请求方式。更棒的是,它基于PromiseXMLHttpRequest
实现。这使得它使用起来更简单、更友好。这也是它比 JavaScript和 jQuery 更受欢迎的原因ajax()
。
JavaScript Fetch API 基础知识
当你想使用 fetch API 发出请求时,你通常需要两样东西。第一个是fetch()
方法。这个方法负责发出请求。它需要一个参数,即你想要发出请求的路径或 URL。除了这个参数之外,你还可以通过配置对象来提供这个方法。
此配置对象是可选的。它允许您为请求设置各种设置。例如,您可以添加标头、包含一些数据的正文、设置跨域请求模式、启用缓存、允许或禁止重定向、指定引荐来源网址和 referrerPolicy 等等。您可以在MDN上找到所有可用选项。
// Fetch syntax
fetch(someURL, {})
// or with optional config object
fetch(someURL, {/* settings go here */})
使用承诺处理函数处理获取
您需要的第二件事是Promise 处理函数。正如我们简要讨论过的,fetch API 基于 Promise。这意味着每次您发出请求时,结果(fetch()
方法返回的数据)都将是一个 Promise。为了处理这个 Promise,您需要使用其中一个 Promise 处理函数。
您可能最常使用的两个处理函数是then()
和catch()
。then()
处理函数帮助您处理 Promise 的已实现状态。这适用于已解决和已拒绝的 Promise。处理已拒绝 Promise 的另一种方法是使用catch()
。
和 都then()
可以catch()
处理已拒绝的 Promise。但是,只有then()
可以处理已解决的 Promise。因此,请确保then()
至少使用 来处理 Promise 的已解决状态。对于已拒绝状态,请确定是否要使用then()
和catch()
。
当 fetch promise 被 fulfilled 时,它收到的数据会自动传递给附加的处理函数。当你需要处理这些数据时,你必须在这些处理函数内部进行操作。如果你想让这些数据在处理函数外部可用,可以将数据赋值给某个外部变量。
// Use fetch() method with promise handler functions
fetch(someUrl)
.then(response => {
// When promise gets resolved
// log received data to console
console.log(response)
})
.catch(error => {
// If promise gets rejected
// log the error to console
console.log(error)
})
// Real-world example
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
// Convert response to JSON format
.then(response => response.json())
// Log the response JSON
.then(jsonData => console.log(jsonData))
.catch(error => {
// If promise gets rejected
// log the error to console
console.log(error)
})
// Output:
// {
// error: false,
// category: 'Programming',
// type: 'twopart',
// setup: 'Programming is like sex.',
// delivery: 'Make one mistake and you end up supporting it for the rest of your life.',
// flags: {
// nsfw: true,
// religious: false,
// political: false,
// racist: false,
// sexist: false
// },
// id: 8,
// lang: 'en'
// }
如上例所示,你可以将 Promise 处理函数一个接一个地串联起来。建议将函数放在then()
最前面,将 放在catch()
后面。如果你还使用了finally()
,建议将其放在最后。
使用 await 处理 fetch
如果您不想使用 Promise 处理函数,另一个选择是await。它await
做两件事。首先,它会暂停周围代码的执行,直到跟在这个关键字后面的 Promise 被满足为止。其次await
,它替换了then()
函数。它会自动提取 Promise 返回的数据并将其赋值给一个变量。
如果要使用 ,需要记住两点await
。首先,请在try...catch语句中使用它。await 是对then()
函数的补充,但它并不对 进行补充catch()
。如果要捕获可能出现的任何错误,可以使用 catchtry...catch
语句。
第二件事是,在顶级 awaitawait
发布之前,你只能在异步函数中使用。这就是你能做的。fetch()
与 with 一起使用await
。然后,用 with 语句包装这两个try...catch
,并将其全部放入async
函数中。
// Create async function
async function makeRequest() {
// Use try...catch statement
try {
// Use await and make fetch request
const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Any')
// Convert the response to JSON format
const responseJSON = await responseData.json()
// Log the converted JSON
console.log(responseJSON)
}
catch (error) {
// Log any error
console.log(error)
}
}
// Call the makeRequest()
makeRequest()
// Output:
// {
// error: false,
// category: 'Miscellaneous',
// type: 'twopart',
// setup: "Mom asked me where I'm taking her to go out to eat for mother's day.",
// delivery: 'I told her, "We already have food in the house".',
// flags: {
// nsfw: false,
// religious: false,
// political: false,
// racist: false,
// sexist: false
// },
// id: 89,
// lang: 'en'
// }
处理响应
当你发出请求时,promise 会返回fetch()
一个响应对象。该对象包含从服务器接收的信息以及各种方法。我们可以使用这些方法来处理数据。这些方法是clone()
、redirect()
、arrayBuffer()
、formData()
、和。blob()
text()
json()
该clone()
方法创建响应的克隆。该redirect()
方法创建一个新的响应,但使用不同的 URL。该方法arrayBuffer()
将响应以ArrayBuffer 的形式返回。该方法将formData()
响应以FormData对象的形式返回。该blob()
方法将响应以 Blob 的形式返回。
以字符串或文本形式返回text()
响应。最后一个方法,即json()
,以 JSON 格式返回响应。您应该使用哪种方法来解析响应取决于您期望的数据类型。例如,如果您期望接收 JSON 格式的数据,则使用json()
,如果是文本格式,则使用text()
,等等。
这些方法的优点在于,您无需知道预期的响应是什么。即使您选择了错误的方法,这些解析响应的方法(例如text()
和 )json()
通常也能正常工作。例如,假设您使用了text()
方法,但响应却是 JSON 格式。
在这种情况下,该text()
方法将能够选择该 JSON 并将其解析为字符串。结果基本上是字符串化的 JSON。但是,该方法不适用于文本响应和json()
。json()
需要特定的语法。如果响应是纯文本,并且您使用json()
,则会收到语法错误。
因此,如果您不确定应该期望哪种类型的响应,请使用text()
。在最坏的情况下,您会得到一些字符串化的 JSON,这样您就知道应该使用json()
哪种格式。如果您期望其他格式,请使用相应的方法:response.formData()
,response.blob()
或response.arrayBuffer()
。
// Example no.1:
// Parsing response as a text
async function makeRequest() {
// Use try...catch statement
try {
// Make fetch request
const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Programming')
// Parsing as Text happens here:
// Parse the response as a text
const responseText = await responseData.text()
// Log the text
console.log(responseText)
}
catch (error) {
// Log any error
console.log(error)
}
}
// Call the makeRequest()
makeRequest()
// Output:
// '{
// error: false,
// category: 'Programming',
// type: 'single',
// joke: 'Programming is 10% science, 20% ingenuity, and 70% getting the ingenuity to work with the science.',
// flags: {
// nsfw: false,
// religious: false,
// political: false,
// racist: false,
// sexist: false
// },
// id: 37,
// lang: 'en'
// }'
// Alternative:
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
.then(response => response.text())
.then(responseText => console.log(responseText))
.catch(err => console.log(err))
// Example no.2:
// Parsing response as a text
async function makeRequest() {
// Use try...catch statement
try {
// Make fetch request
const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Programming')
// Parsing as JSON happens here:
// Parse the response as a JSON
const responseJSON = await responseData.json()
// Log the JSON
console.log(responseJSON)
}
catch (error) {
// Log any error
console.log(error)
}
}
// Call the makeRequest()
makeRequest()
// Output:
// {
// error: false,
// category: 'Programming',
// type: 'twopart',
// setup: 'How do you generate a random string?',
// delivery: 'Put a Windows user in front of Vim and tell him to exit.',
// flags: {
// nsfw: false,
// religious: false,
// political: false,
// racist: false,
// sexist: false
// },
// id: 129,
// lang: 'en'
// }
// Alternative:
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
.then(response => response.json())
.then(responseJSON => console.log(responseJSON))
.catch(err => console.log(err))
正在处理已经处理的响应
当您使用一种方法处理响应并将其解析为一种格式时,您无法再次处理它并将其解析为另一种格式。如果您将响应解析为文本,则无法再将其解析为 JSON 格式。解析一次响应后,它将被锁定。再次解析将导致 TypeError。
async function makeRequest() {
// Use try...catch statement
try {
// Make fetch request
const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Programming')
// Parse the response as a text
const responseText = await responseData.text()
// This will not work after the first parsing
// Try to parse the response again as a JSON
const responseJSON = await responseData.json()
// Log the text
console.log(responseText)
// Log the JSON
console.log(responseJSON)
}
catch (error) {
// Log any error
console.log(error)
}
}
// Call the makeRequest()
makeRequest()
// Output:
// TypeError: Failed to execute 'json' on 'Response': body stream is locked
使用 fetch 发起请求
该方法默认的请求类型fetch()
是GET
。如果您想更改请求类型,可以进行更改。您可以通过可选的配置对象(可将其作为第二个参数传递给该fetch()
方法)来更改请求类型。例如,您可以设置method
为POST
来发出POST
请求,等等。
GET 请求
如果按原样使用该fetch()
方法并仅提供 URL,它将自动执行GET
请求。
// GET request example
async function makeGetRequest() {
// Use try...catch statement
try {
// Make GET fetch request
const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Programming')
// Parse the response as a JSON
const responseJSON = await responseData.json()
// Log the JSON
console.log(responseJSON)
}
catch (error) {
// Log any error
console.log(error)
}
}
// Call the makeGetRequest()
makeGetRequest()
// Output:
// {
// error: false,
// category: 'Programming',
// type: 'single',
// joke: "Knock knock.
// Who's there?
// Recursion.
// Recursion who?
// Knock knock.",
// flags: {
// nsfw: false,
// religious: false,
// political: false,
// racist: false,
// sexist: false
// },
// id: 182,
// lang: 'en'
// }
// Alternative with promise handler functions:
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
.then(response => response.json())
.then(responseJSON => console.log(responseJSON))
.catch(err => console.log(err))
POST 请求
另一种常见的请求类型是POST
。您可以通过更改 on 配置对象来使用 fetch API 发出此类请求method
。此对象是您可以传递给 的第二个可选参数fetch()
。如果您将 设置method
为 ,POST
该fetch()
方法将执行POST
请求。
发出POST
请求时,您需要发送一些数据。您可以通过body
选项添加这些数据。此选项也包含在配置对象中。此外,您可能还想更改Content-Type
。您可以通过headers
选项执行此操作。但是,对于简单的请求,POST
仅method
和body
可能就足够了。
// Some data to send
const userData = {
firstName: 'Tom',
lastName: 'Jones',
email: 'tom@jones.ai'
}
// Make POST request
async function makePostRequest() {
// Use try...catch statement
try {
// Make fetch request
const responseData = await fetch('/users/register', {
method: 'POST', // Change the request method
headers: { // Change the Content-Type
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(userData) // Add data you want to send
})
// Parse the response as a JSON
const responseJSON = await responseData.json()
// Log the JSON
console.log(responseJSON)
}
catch (error) {
// Log any error
console.log(error)
}
}
// Call the makePostRequest()
makePostRequest()
// Alternative with promise handler functions:
fetch('/users/register', {
method: 'POST', // Change the request method
headers: { // Change the Content-Type
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(userData) // Add data you want to send
})
.then(response => response.json())
.then(responseJSON => console.log(responseJSON))
.catch(err => console.log(err))
DELETE 请求
当您想要删除某些数据、文件等时,可以发出DELETE
请求。发出此类请求所需的语法比 略多GET
,但比 少POST
。您需要做的是将 选项设置为method
。然后,您需要知道正确的 URL 以及要删除的内容。fetch()
DELETE
// Make DELETE request
async function makeDeleteRequest() {
// Use try...catch statement
try {
// Make fetch request
const responseData = await fetch('/users/tom', {
method: 'DELETE' // Change the request method
})
// Parse the response as a JSON
const responseJSON = await responseData.json()
// Log the JSON
console.log(responseJSON)
}
catch (error) {
// Log any error
console.log(error)
}
}
// Call the makeRequest()
makeDeleteRequest()
// Alternative with promise handler functions:
fetch('/users/tom', {
method: 'DELETE', // Change the request method
})
.then(response => response.text())
.then(responseText => console.log(responseText))
.catch(err => console.log(err))
PUT 请求
请求类型PUT
最常用于更新现有数据或资源。此请求看起来与 几乎相同POST
。主要(有时也是唯一的)区别在于method
的选项fetch()
必须设置为PUT
。
// Some data to send to update existing records
const userData = {
firstName: 'Jack',
lastName: 'O\'Brian',
email: 'jack@obrian.co'
}
// Make Put request
async function makePutRequest() {
// Use try...catch statement
try {
// Make fetch request
const responseData = await fetch('/users/jack', {
method: 'PUT', // Change the request method
body: JSON.stringify(userData) // Add data you want to send
})
// Parse the response as a JSON
const responseJSON = await responseData.json()
// Log the JSON
console.log(responseJSON)
}
catch (error) {
// Log any error
console.log(error)
}
}
// Call the makePutRequest()
makePutRequest()
// Alternative with promise handler functions:
fetch('/users/jack', {
method: 'PUT', // Change the request method
body: JSON.stringify(userData) // Add data you want to send
})
.then(response => response.json())
.then(responseJSON => console.log(responseJSON))
.catch(err => console.log(err))
PATCH 请求
这PATCH
是我们将要讨论的最后一种使用 fetch API 的请求类型。这种请求与 非常相似PUT
。两者的区别在于PUT
用于用新版本更新旧版本。这意味着您可以更新所有内容。而PATCH
则仅更新部分现有数据,例如用户电子邮件地址。
// Some data to send to update
// only a part of existing records
const userData = {
email: 'jack@obrian.co'
}
// Make PATCH request
async function makePatchRequest() {
// Use try...catch statement
try {
// Make fetch request
const responseData = await fetch('/users/jack', {
method: 'PATCH', // Change the request method
body: JSON.stringify(userData) // Add data you want to send
})
// Parse the response as a JSON
const responseJSON = await responseData.json()
// Log the JSON
console.log(responseJSON)
}
catch (error) {
// Log any error
console.log(error)
}
}
// Call the makePatchRequest()
makePatchRequest()
// Alternative with promise handler functions:
fetch('/users/jack', {
method: 'PATCH', // Change the request method
body: JSON.stringify(userData) // Add data you want to send
})
.then(response => response.json())
.then(responseJSON => console.log(responseJSON))
.catch(err => console.log(err))
关于 Response 对象的说明
我们简要讨论了 Response 对象上可以使用的方法:text()
、json()
、formData()
、blob()
、和。这些方法并非 Response 对象的全部。它还包含许多属性。您可能会发现其中一些属性很有用arrayBuffer()
。clone()
redirect()
一些最有用的属性是statusText
、status
和ok
。statusText
是包含 HTTP 状态代码消息的字符串。status
是一个数字,用于指定响应的状态代码。当您发出请求并成功时,它将具有status
200 的值。
是ok
一个布尔值,指定 是否status
在 200 到 299 的代码范围内。因此,如果您的请求成功,即 200, 的值ok
将为true
。此外,还有一个body
属性。此属性包含您收到的数据。当您使用某些方法解析响应时,它会与此body
属性配合使用。
// Make fetch request
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
.then(response => console.log(response)) // Log the Response object
.catch(err => console.log(err))
// Output:
// {
// body: (...)
// bodyUsed: false
// headers: Headers
// ok: true
// redirected: false
// status: 200
// statusText: ""
// type: "cors"
// url: "https://sv443.net/jokeapi/v2/joke/Programming"
// }
结论:JavaScript Fetch API 入门
JavaScript Fetch API 提供了一种简单易用的请求方式。希望本教程能帮助您了解 Fetch API 是什么以及它的工作原理。也希望我们之前的示例能帮助您理解如何使用这个 API,以及如何成功发出请求以及如何正确处理响应。
鏂囩珷鏉ユ簮锛�https://dev.to/alexdevero/getting-started-with-the-javascript-fetch-api-373k