目录
1. 网络请求的基本概念
1.1 网络请求的基础HTTP协议
1.2 HTTP工作原理
1.3 TCP连接
1.31 建立TCP连接
1.31 关闭TCP连接
1.4 HTTP的请求方法
1.5 HTTP的响应状态码分类
1.6. 前端网络请求方式
2. Axios在在vue项目中的使用
2.1安装与使用
2.2 Axios使用HTTP请求方法
2.21 POST
2.22 GET
2.23 PUT
2.24 PATCH
2.25 DELETE
2.26 HEAD
2.27 OPTIONS
2.28 REQUEST
2.29 Axios请求方法补充
2.3 执行多个并发
2.4 Axios实例
2.5 Axios拦截器
2.51 请求拦截器
2.52 响应拦截器
2.53 移除拦截器
2.54 实例添加拦截器
2.6 错误处理
2.7 取消请求
2.8 Axios封装
1. 网络请求的基本概念
前端网络请求是Web开发中不可或缺的一部分,它涉及客户端(通常是浏览器)与服务器之间的数据交换。
参考文章:HTTP 教程 | 菜鸟教程 (runoob.com)
1.1 网络请求的基础HTTP协议
HTTP 是一种本地浏览器获取服务器中诸如 HTML 文档这类资源的应用层网络传输协议。
它是万维网(WWW)的数据通信基础,设计目的是确保客户端与服务器之间的通信。
它工作于客户端 —— 服务器架构之上,通过请求 —— 响应模型进行通信。浏览器作为HTTP客户端通过URL向HTTP服务器端(即WEB服务器)发送请求,服务器根据接收到的请求向客户端发送响应信息。
1.2 HTTP工作原理
一个典型的网络请求过程通常包括以下几个步骤:
建立连接:客户端和服务器之间建立TCP连接。
发送请求:客户端通过HTTP等协议向服务器发送请求报文。
处理请求:服务器接收并解析客户端的请求,根据请求的内容进行相应的处理,如查询数据库、执行逻辑操作等。
发送响应:服务器将处理结果封装成HTTP响应,发送给客户端。
关闭连接:非持久连接,在数据传输完成后,客户端和服务器关闭TCP连接。持久连接,则保持连接以进行后续的数据交换。
渲染页面:客户端接收到响应后,根据响应内容(如HTML、图片等)渲染页面,展示给用户。
1. 请求报文由请求行、请求头部、空行和请求体四个部分组成
请求行:请求方法( GET、POST等),请求的资源路径(URI),HTTP协议版本(如 HTTP/1.1 或 HTTP/2)。格式示例:GET /index.html HTTP/1.1/.....
请求头:包含了客户端环境信息、请求体的大小(如果有)、客户端支持的压缩类型等。空行:请求头和请求体之间的分隔符,表示请求头的结束请求体(可选):在某些类型的HTTP请求(如 POST 和 PUT)中,请求体包含要发送给服务器的数据
2. HTTP 响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
状态行:HTTP 协议版本(与请求消息中的版本相匹配),状态码(表示请求的处理结果),状态信息(状态码的简短描述)。格式示例:HTTP/1.1 200 OK
响应头:包含了服务器环境信息、响应体的大小、服务器支持的压缩类型等。
空行:响应头和响应体之间的分隔符,表示响应头的结束。
响应体(可选):包含服务器返回的数据,如请求的网页内容、图片、JSON数据等。
参考:HTTP 消息结构 | 菜鸟教程 (runoob.com)
1.3 TCP连接
TCP是一种面向连接的的传输层通信协议。它负责确保数据在传输过程中的可靠性、完整性和顺序性。TCP连接通过著名的 “三次握手” 和 “四次挥手” 机制建立和关闭。
1.31 建立TCP连接
三次握手的目的是,确保了通信双方都能够准备好进行数据传输。
第一次握手:客户端向服务器发送一个SYN(同步序列编号)报文段,并包含自己的初始序列号seq=x。这个报文段表示客户端想要与服务器建立连接。此时,客户端进入SYN-SENT(同步已发送)状态。
第二次握手:服务器收到客户端的SYN报文段后,会向客户端发送一个SYN-ACK(同步确认)报文段作为应答。这个报文段包含服务器的初始序列号seq=y,以及对客户端SYN报文段的确认号ack=x+1。此时,服务器进入SYN-RCVD(同步收到)状态。
第三次握手:客户端收到服务器的SYN-ACK报文段后,会向服务器发送一个ACK(确认)报文段。这个报文段包含对服务器SYN-ACK报文段的确认号ack=y+1,以及自己的序列号seq=x+1(此时,序列号已经因为第一次发送SYN报文段而增加)。当服务器收到这个ACK报文段后,连接就建立了,双方进入ESTABLISHED(已建立连接)状态,可以开始传输数据了。
1.31 关闭TCP连接
“四次挥手” 的目的是,确保了通信双方都能够安全地关闭连接,并释放相关资源。
第一次挥手:客户端向服务器发送一个FIN(结束)报文段,表示客户端没有更多的数据要发送了。此时,客户端进入FIN-WAIT-1(终止等待1)状态。
第二次挥手:服务器收到客户端的FIN报文段后,会向客户端发送一个ACK报文段作为应答。这个报文段包含对客户端FIN报文段的确认号,表示服务器已经收到了客户端的关闭请求。此时,服务器进入CLOSE-WAIT(关闭等待)状态,而客户端进入FIN-WAIT-2(终止等待2)状态。
第三次挥手:服务器在发送完所有剩余的数据后,会向客户端发送一个FIN报文段,表示服务器也没有更多的数据要发送了。此时,服务器进入LAST-ACK(最后确认)状态。
第四次挥手:客户端收到服务器的FIN报文段后,会向服务器发送一个ACK报文段作为应答。这个报文段包含对服务器FIN报文段的确认号。当服务器收到这个ACK报文段后,连接就关闭了。此时,客户端和服务器都进入CLOSED(已关闭)状态。
1.4 HTTP的请求方法
HTTP/1.1协议中共定义了 9 种方法(也叫“动作”)来以不同方式操作指定的资源:
序号 | 方法 | 描述 |
---|---|---|
1 | GET | 从服务器获取资源。用于请求数据而不对数据进行更改。例如,从服务器获取网页、图片等。 |
2 | POST | 向服务器发送数据以创建新资源。常用于提交表单数据或上传文件。发送的数据包含在请求体中。 |
3 | PUT | 向服务器发送数据以替换更新现有资源,它期望用请求体中的完整资源表示来替换服务器上对应URI的资源。如果资源不存在,则创建新的资源。与 POST 不同,PUT 通常是幂等的,即多次执行相同的 PUT 请求不会产生不同的结果。 |
4 | DELETE | 从服务器删除指定的资源。请求中包含要删除的资源标识符。 |
5 | PATCH | 对资源进行部分更新。与 PUT 类似,但 PATCH 只更改部分数据而不是替换整个资源。它期望只包含需要修改的资源的一部分,而不是整个资源的完整表示 |
6 | HEAD | 类似于 GET,但服务器只返回响应的头部,不返回实际数据。用于检查资源的元数据(例如,检查资源是否存在,查看响应的头部信息)。 |
7 | OPTIONS | 返回服务器支持的 HTTP 方法。用于检查服务器支持哪些请求方法,通常用于跨域资源共享(CORS)的预检请求。 |
8 | TRACE | 回显服务器收到的请求,主要用于诊断。客户端可以查看请求在服务器中的处理路径。 |
9 | CONNECT | 建立一个到服务器的隧道,通常用于 HTTPS 连接。客户端可以通过该隧道发送加密的数据。 |
1.5 HTTP的响应状态码分类
状态码( status code ),来指明对应请求已成功执行或是没有,以及相应的原因。
状态码分类 | 分类描述 |
100 —— 199 | 一般信息。表示接收到的请求正在处理 |
200 —— 299 | 成功响应。表示请求正常处理完毕 |
300 —— 399 | 重定向。表示需要进一步操作以完成该请求 |
400 —— 499 | 客户端错误。表示请求语法错误或无法完成 |
500 —— 599 | 服务器错误。表示服务器在处理请求过程中发生了错误 |
1.6. 前端网络请求方式
前端进行网络请求的方式多种多样,主要包括:
方式 | 介绍 |
XMLHttpRequest(XHR) | 最早和最常见的网络请求方式之一,允许客户端与服务器进行 异步通信。XHR API 提供了一个在后台发送 HTTP 请求和接收响应的机制,使得页面能够在不刷新的情况下更新部分内容 |
Fetch API | 更强大、更灵活、更友好的 API。它使用 Promise 对象,简化了对网络请求的处理(promise的链式调用)。 |
jQuery的Ajax方法 | jQuery是一个快速、小巧、功能丰富的JavaScript库,其中包含了 简化 Ajax 调用的方法。 |
Axios | 扩展了 Fetch API,提供了更丰富的功能。在一些大型框架中会被使用,例如Vue.js。 |
WebSocket | 虽然 WebSocket 严格来说不是一种发起网络请求的方式,但它提供了一种在单个 TCP 连接上进行全双工通讯的协议。它允许服务器主动向客户端推送数据,而无需客户端轮询。 |
Ajax发展简介:
在旧浏览器页面在向服务器请求数据时,因为返回的是整个页面的数据,页面都会强制刷新一下,这对于用户并不是很友好。并且我们只需要修改页面的部分数据,而从服务器端发送的却是整个页面的数据,十分消耗网络资源。为了降低资源消耗,提高用户使用体验,异步网络请求应运而生。
Ajax(Asynchronous JavaScript and XML,即异步的JS和XML),它使网页网页能够在不重新加载整个页面的情况下与服务器交换数据并更新页面的一部分,从而提升了用户体验并减少了网络资源的消耗。
实现Ajax的方式有多种(且本质上都是对原生的XHR的封装),但都有利弊:
方式 | 优点 | 缺点 |
原生XHR | 所有现代浏览器都原生支持 | 配置,调用方式繁琐复杂 |
jQuery封装的Ajax | 简化了XMLHttpRequest的使用,提供了更简洁的API和丰富的配置选项 | 增加了项目对jQuery的依赖和体积 |
Fetch API | 基于Promise,步处理机制简洁强大。 是现代浏览器的一部分,不需要额外的库或框架 | 默认配置较简单,可能需要手动设置一些选项(如请求头、凭据等) |
Axios | 上面有的优点它基本都有,API 简洁,功能强大 | / |
2. Axios在在vue项目中的使用
Axios 是基于 promise 的网络请求库,作用于node.js和浏览器中。
特点:
从浏览器创建 XMLHttpRequests请求从node.js创建http请求支持 Promise API拦截请求和响应,比如:在请求前添加授权和响应前做一些事情。转换请求数据和响应数据,比如:进行请求加密或者响应数据加密。取消请求自动转换JSON数据客户端支持防御XSRF参考文档:Axios中文文档
2.1安装与使用
1)安装axios
$ npm install axios
2)在组件中使用axios
import axios from 'axios'axios(request).then((res) => {console.log("响应",res)}) .catch((err) => {console.log(err)})
注意:
①这里的request是请求体,包含请求行、请求头部、空行和请求数据等。
②axios是异步的,也是基于Promise 对象的,需要使用Promise API或asyc/await等异步处理方式等待promise解析完成,才能拿到结果。
③在使用Axios进行HTTP请求时,返回的res代表整个响应对象,(它包含如status
(HTTP状态码),statusText
(状态信息),data
(服务器返回的实际数据),headers
(响应头)等多个属性)。res.data才是包含了服务器响应的实际数据(body),也是大多数情况,我们需要用于渲染的数据。如下:
响应结构:一个请求的响应包含以下信息
{ // `data` 由服务器提供的响应 data: {}, // `status` 来自服务器响应的 HTTP 状态码 status: 200, // `statusText` 来自服务器响应的 HTTP 状态信息 statusText: 'OK', // `headers` 是服务器响应头 // 所有的 header 名称都是小写,而且可以使用方括号语法访问 // 例如: `response.headers['content-type']` headers: {}, // `config` 是 `axios` 请求的配置信息 config: {}, // `request` 是生成此响应的请求 // 在node.js中它是最后一个ClientRequest实例 (in redirects), // 在浏览器中则是 XMLHttpRequest 实例 request: {}}
2.2 Axios使用HTTP请求方法
2.21 POST
axios.post( url , data , config ),创建新资源
url
是请求的资源路径。config
(可选)是一个配置对象,可以包含请求头、查询参数等。
data
(可选)是作为请求体发送的数据
axios.post('https://api.example.com/goods',{//data sale:1000, name: '又大又红的小苹果' },{ //其他配置 headers:{// 请求头 ..... }}).then(res=>{console.log(res)}) .catch((err) => {console.log(err)})
如上:假设我们https://api.example.com/goods向发送post请求创建一个资源,并在后端生成并返回了一个 资源的唯一标识符 id : 1。
2.22 GET
axios.get( url , config ),获取资源
url
是资源路径。config
(可选)是一个配置对象
//请求格式 https://api.example.com/goods?id=1axios.get('https://api.example.com/goods',{ //其他配置 params:{// 查询参数,用于get请求 id:1 }, headers:{// 请求头 ..... }}).then(res=>{console.log(res.data)}) .catch((err) => {console.log(err)})
如上:我们通过查询参数(此处是上面POST创建的资源的唯一标识符id :1),获取到资源
2.23 PUT
axios.put( url , data , config ),对现有资源替换更新,或创建不存在的资源
参数与 axios.post 相同
axios.put('https://api.example.com/goods',{//put更新了sale id: 1, sale:2600, name: '又大又红的小苹果' },{ headers:{// 请求头 ..... }}).then(res=>{console.log(res)}) .catch((err) => {console.log(err)})
如上:我们将put所期望的完整资源一同发送,进行资源替换修改
2.24 PATCH
axios.patch( url , data , config ),对资源部分更新
参数与 axios.post 相同
axios.patch('https://api.example.com/data/big-apple',{//data id: 1, sale:4550,},{ //其他配置 headers:{// 请求头 ..... }}).then(res=>{console.log(res)}) .catch((err) => {console.log(err)})
如上:我们将需要修改的资源的一部分通过patch发送(注意:唯一标识符是必需的)
2.25 DELETE
axios.delete( url , config ),删除资源
url
是资源路径。config
(可选)是一个配置对象。注意,delete 请求通常不需要请求体,但也可以通过配置对象 config 发送查询参数。
axios.delete('https://api.example.com/goods',{ //其他配置 params:{ id:1// 资源标识符作查询参数,用于delete }, headers:{// 请求头 ..... }}).then(res=>{console.log(res)}) .catch((err) => {console.log(err)})
如上:我们将资源唯一标识符 id作为查询参数发送delete请求
2.26 HEAD
axios.head( url , config ),获取响应头部
head 请求与 get 请求类似,但服务器不会在响应中返回消息体,而只返回响应头部。
axios.head('https://api.example.com/goods',{ //其他配置......config对象}).then(res=>{console.log(res.headers)}) // 响应头在res.headers中 .catch((err) => {console.log(err)})
如上:使用head方法和get类似,都会返回一个完整的响应对象,但res.data中是没有数据的,返回的响应头在res.header中
2.27 OPTIONS
axios.potions( url , config ),获取HTTP支持的方法
axios.potions('https://api.example.com/goods',{ //其他配置......config对象}).then(res=>{console.log(res.headers)}) .catch((err) => {console.log(err)})
如上: OPTIONS 请求用于描述目标资源的通信选项。响应头在response.headers中,并可能包含CORS信息等 。
2.28 REQUEST
axios.request( config ),通用方法
axios.request({ method: 'post', url: 'https://api.example.com/goods', data: { sale: '6666', name: '大香蕉' } }).then(res=>{console.log(res.headers)}) .catch((err) => {console.log(err)})
如上:这是 Axios 的通用请求方法,允许你传递一个配置对象来发送请求。你可以在这个配置对象中指定请求方法(method)、URL(url)、请求头(headers)、请求体(data/params)等。
2.29 Axios请求方法补充
① Axios 没有直接用于追踪(trace)请求的方法。
因为在 HTTP/1.1 和 HTTP/2 协议中,TRACE 方法主要用于诊断目的,但在实际应用中由于其安全风险(如跨站追踪攻击 XSS)而被广泛禁用或不建议使用。
如果需要在 Axios 中进行某种形式的“追踪”或日志记录,可以通过添加拦截器来实现
②Axios 没有 connect 方法,它主要用于 HTTP/1.1 协议的代理服务器或网关,以及 WebSocket 握手过程中。在标准的 Web 开发中,开发者很少会直接使用 CONNECT
方法来发送请求,因为它主要用于需要代理或隧道的情况。
③虽然Axios提供了多种便捷的语法糖(axios.get....等),但所有这些方法背后实际上都是基于axios.request(config)方法来实现的。因此,理论上你可以使用axios({请求对象})的格式来发起任何其他类型的HTTP请求。
④Axios使用HTTP请求时,如果涉及到需要数据传输,则视数据情况,项目规范情况,可能会被放在请求体,也可能会被放在url中....,不一定如上述方法举例的那样。
2.3 执行多个并发
axios.all( ) 方法,用于同时执行多个异步的 HTTP 请求。它和Promise.all( )执行机制是一样的,要么全部成功走then,要么就走catch
// 定义两个异步的GET请求 const getUser = axios.get('/user/12345'); const getPosts = axios.get('/posts'); // 使用axios.all同时执行这两个请求,并使用解构赋值展开结果数组axios.all([getUser, getPosts]) .then(([userResponse, postsResponse]) => { console.log('User:', userResponse.data) console.log('Posts:', postsResponse.data) }) .catch(errors => {console.error(errors)})
2.4 Axios实例
通过 axios.create( config )创建实例,如:
const instance = this.axios.create({baseURL: 'https://api.example.com',timeout: 2000//超时时间})instance.get('/goods').then(res=>{ console.log(res.data)})
如上:我们可以在axios实例上配置一些默认设置。这对于需要发送多个请求到同一域,并且这些请求共享某些配置(如基础 URL、请求头等)时非常有用。
axios实例常用配置:
参数 | 解释 | 数据类型 |
baseURL | 请求的域名,基本地址 | String |
timeout | 请求超时时长,单位ms | Number |
url | 请求路径 | String |
method | 请求方法 | String |
headers | 设置请求头 | Object |
params | 请求参数,参数将被拼接在URL上 | Object |
data | 请求参数,参数将被放到请求体中 | Object |
maxContentLength | 响应数据的最大字节数,超出则拒绝响应 | Number |
withCredentials | 表示跨站请求时是否携带cookie。默认false | boolean |
proxy | 代理服务器主机名称和端口。用于绕过CORS(跨源资源共享)策略,或者用于调试目的 | String 或 Object |
注意:即使进行了实例配置,但在使用实例进行实际请求时,依然可以再进行配置。如下
//实例配置let instance = axios.create();instance.defaults.timeout = 3000;//请求配置instance.get('/goods',{timeout: 4000})
这种规则对全局配置同样生效,配置优先级:请求配置 > 实例配置 > 全局配置
2.5 Axios拦截器
在请求或响应被 then 或 catch 处理前拦截它们。如下:为axios添加拦截器
2.51 请求拦截器
在请求发起之前,对请求进行某些处理,如:添加token信息
axios.interceptors.request.use( (config) => { //在发起请求之前应该做些什么 return config }, // 对请求错误做些什么 (err) => Promise.reject(err))
2.52 响应拦截器
在响应收到之后,对响应进行某些处理,如:验证信息内容,直接返回res.data
axios.interceptors.response.use(function (response) { // 2xx 范围内的状态码都会触发该函数。 // 对响应数据做点什么 return response; }, function (error) { // 超出 2xx 范围的状态码都会触发该函数。 // 对响应错误做点什么 return Promise.reject(error); });
2.53 移除拦截器
通过eject(),我们可以移除添加的拦截器
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});axios.interceptors.request.eject(myInterceptor);
2.54 实例添加拦截器
可以给自定义的 axios 实例添加拦截器。
const instance = axios.create();instance.interceptors.request.use(function () {/*...*/});
2.6 错误处理
请求拦截器和响应拦截器抛出错误时,返回的err对象会传给当前函数的err对象。同时,你可以使用 validateStatus 配置选项,来自定义会抛出错误的 HTTP code。
axios.get('/url',{ validateStatus: function (status) { return status < 500; // 处理状态码小于500的情况 }}).then(res={ //.... }).catch(err=>{ //打印错误信息console.log(err);})
2.7 取消请求
常用于在请求拦截器中
let source = axios.CancelToken.source()axios.get('/goods',{cancelToken: source}).then(res=>{console.log(res)}).catch(err=>{//取消请求后会执行该方法console.log(err)})//取消请求,参数可选,该参数信息会发送到请求的catch中source.cancel('取消后的信息')
2.8 Axios封装
utils / request.js文件:这是封装axios的文件,对axios的配置都放在这里
import axios from "axios"const baseURL = "https://restapi.amap.com"const instance = axios.create({ // 基础地址,超时时间 baseURL, timeout: 10000,})// 请求拦截器instance.interceptors.request.use( (config) => { //请求处理,如:携带token config.headers.Authorization = token return config; }, //请求错误处理 //如:请求配置(url,请求方法..)错误,跨域问题等 (err) => Promise.reject(err)//抛出错误)// 响应拦截器instance.interceptors.response.use( (res) => { //响应处理,状态码300以内,响应会在此处被接收处理 return res }, (err) => { // 响应错误处理,状态码300以,外响应会在此处被接收处理,比如: // 客户端错误处理4xxx => 如:用户未登录,没有权限, 拦截到登录 if (!isAuthenticated) router.push("/login") return Promise.reject(err)//抛出错误 })export default instance
api/index.js文件:这是api的请求文件,用于单独管理api请求方法
import request from "@/utils/request";export const getTestService = (config) => request.get("/v3/weather/weatherInfo", config);
在组件中使用这个接口:
<script setup>import { getTestService } from '@/api'function getData() { const config = { params: { city: "110101", key: "个人密钥key", }, } getTestService(config) .then((res) => { console.log(res) }) .catch((err) => { console.log(err) })}getData()</script>
请求响应结果:
vue文件结构:
代码中,测试使用的api:高德天气API
若有错误或描述不当的地方,烦请评论或私信指正,万分感谢 ?