翻译原文:https://dev.to/aminnairi/the-5-pillars-of-every-http-request-18ld
一个成功的 HTTP 请求不仅仅意味着简单地发送一个请求并接收到响应。事实上,每个 HTTP 请求都需要具备五大要点,这些要点确保了请求的正确性、可靠性和用户体验。在本文中,我们将探讨这五大要点,即发送适当的请求、显示加载状态、处理错误、请求可取消以及验证接收到的数据。通过深入了解这些要点,我们可以更好地理解 HTTP 请求的本质,并构建出更健壮、高效的网络项目。
一、请求(Request)
请求,或者说是 HTTP 请求,是向服务器发送的一个动作,目的是获取某些信息或者发送一些信息。这包括服务器的 URL、请求头和请求体。大部分将要解释的内容都是在请求某些信息时很重要的,但也可以在发送信息时应用。
二、加载(Loading)
为用户显示加载信息是请求的一个重要步骤,因为我们永远不知道网络会发生什么,也许连接很慢,也许服务器因为众多请求而变慢。
显示一个加载器或者一个文本指示请求仍在进行中是一个额外的步骤,可以使你的项目看起来更专业,更用户友好,而不是认为每个人都有快速的互联网连接。
你可以在你最喜欢的浏览器中,如 Firefox 或 Google Chrome 的开发者控制台中模拟减慢(3G网络、2G网络等)的请求。
三、错误(Error)
网络中会发生各种各样的事情,我们无法控制除了我们代码内部发生的事情之外的一切。
网络可能会暂时关闭,或者用户已经激活了飞行模式,或者服务器已经停止了一段时间。我们永远不知道可能会出现什么样的问题,或者什么时候会发生,但我们知道可能会出现一些问题,我们必须考虑到这一点。
在代码中考虑到这些问题是一个好的实践,特别是在 JavaScript 中,因为发送请求通常涉及使用 Promise,而 Promise 可能处于被拒绝的状态。
你也可以在你的浏览器中模拟离线连接,在开发者控制台中进行。
四、可取消(Cancelable)
如果你计划从远程 API 为用户提供数据,则至少提供一种取消这些请求的方法。
这是任何项目中的良好实践和附加用户体验,因为从远程服务器获取大量负载可能对使用数据计划的用户来说是昂贵的,并且选择是向你的用户展示你正在考虑每个人,即使是那些无法承担大量数据传输的人的好方法。
使用 JavaScript 和 Web API Fetch,你可以使用信号以及 Abort Controller 来提供取消请求的方法。
五、验证(Validation)
最后,你已发送请求,一切都按计划进行,并收到成功的响应。或者有可能失败?
你如何确保服务器不会在一天、一周或一年内更改其响应?你的项目可能会运行一段时间,但如果有人决定发送一个带有属性而不是常见的数组的对象,你可能会遇到麻烦,因为你将尝试迭代一个对象而不是一个数组,这在 JavaScript 中是不可能的。
数据验证是一个重要的步骤,在某些情况下可能是强制性的,因为即使你今天知道自己在做什么,并且是前端和后端项目的唯一开发人员,但你在一年内可能不是一个人在开发这个项目,可能会有其它同事加入项目的开发。
如果你从长假回来,API 已更改,至少通过数据验证,你知道这是你考虑过的情况,你的项目不会突然崩溃(你甚至可能会获得更好的错误,这将使你更快地解决此错误而不需要数据验证)。
此外,通过数据验证,你可以依赖强类型的语言(如 TypeScript)来确保一旦解析和验证了此数据,你可以百分之百地确定可以迭代它,而不是担心它可能在不久的将来发生变化。
这是一个在 React 中的初学者项目示例:
import React, { useEffect, useState } from "react" export const App = () => { const [users, setUsers] = useState([]) useEffect(() => { fetch("https://jsonplaceholder.typicode.com/users") .then((response) => { return response.json() }) .then((newUsers) => { setUsers(newUsers) }) }, []) return ( <ul> {users.map((user) => ( <li key={user.id}>{user.username}</li> ))} </ul> ) }
可以看到,没有加载状态、可取消的请求、错误处理或数据验证。下面是添加了这些功能后的代码:
import React, { Fragment, useRef, useEffect, useState, useCallback } from "react" const isValidUser = (input) => { return ( typeof input === "object" && input !== null && typeof input.id === "number" && typeof input.username === "string" ) } const isValidUsers = (users) => { if (!Array.isArray(users)) { return false } if (!users.every((user) => isValidUser(user))) { return false } return true } export const App = () => { const [users, setUsers] = useState([]) const abortController = useRef(null) const [error, setError] = useState(null) const [loading, setLoading] = useState(false) const cancel = useCallback(() => { abortController?.current?.abort() }, [abortController]) useEffect(() => { abortController.current = new AbortController() const { signal } = abortController.current setError(null) setLoading(true) fetch("https://jsonplaceholder.typicode.com/users", { signal }) .then((response) => { if (response.ok) { return response.json() } return Promise.reject(new Error("Something went wrong")) }) .then((newUsers) => { if (!isValidUsers(newUsers)) { throw new Error("Wrong response from the server") } setUsers(newUsers) }) .catch((error) => { if (error.name !== "AbortError") { setError(error) } }) .finally(() => { setLoading(false) }) return cancel }, [cancel]) return ( <Fragment> {loading && <div>Loading...</div>} {error && <div>Error: {error.message}</div>} <ul> {users.map((user) => ( <li key={user.id}>{user.username}</li> ))} </ul> </Fragment> ) }
当然,没有应用样式,所以看起来不是很方便,但至少你有了一个想法。
我们添加了一种取消请求的方式,一个加载指示来向用户保证,一个显示任何错误的机制,以及一个基本的数据验证机制,以确保我们获得的数据没有被损坏或更改。
要点总结
我们看到,为了构建可靠的项目,每当我们向服务器发出请求时,必须遵循 5 大要点:
- 发送适当的请求
- 显示加载状态
- 如果有任何错误,则显示错误
- 使请求可取消
- 验证我们收到的数据如果你能够遵循这些步骤,你将构建高度可靠的项目,这些概念不仅适用于 JavaScript 和 React,而且可以应用于几乎任何语言或任何框架和库,只要你遵循这些步骤。
使用工具进行接口管理
在项目开发或者测试的过程中,API 的校验是必要的。项目中具备的功能如果只是用手去“点测”是不实际的,因为一个项目几百上千条接口,花费的时间过于庞大。 那么,如何简化这个过程,使得工作效率更高呢?可以试试 Apifox,一个强大而易于使用的 API 管理平台。
Apifox 提供简洁直观的界面,帮助你发送适当的请求,并显示加载状态。同时,当出现错误时,Apifox 能够快速捕捉并显示错误信息,让你更快地定位和解决问题。