关于浏览器请求队列和超时表现(canceled)

article/2025/9/16 21:28:04

前端在向服务器 API 发送请求时一般会设置一个超时时间,避免超过期望时间的持续等待。

以 Axios 为例,一般会设置 timeout 请求超时选项。

但是浏览器判断超时并不是这么简单。

搭建环境

express + axios 搭建 web 服务。

在项目目录下安装依赖:npm i express axios

添加文件:

// start.js
const express = require('express')const PORT = 3000let app = express()app.use(express.static(path.join(__dirname, 'public')))
app.use('/api', require('./timeout'))app.listen(PORT, () => {console.log(`Sever listening on port ${PORT}`)
})
// timeout.js
const express = require('express');const router = express.Router()router.get('/timeout', async (req, res) => {// 用于查看服务器接收到请求的时机console.log('timeout')// 5 秒后响应setTimeout(() => {res.status(200).end('OK')}, 5000);
})module.exports = router
<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script></head><body><script>const instance = axios.create({timeout: 1000 // 超过1秒超时,中止请求})function fetch() {instance.get('/api/timeout')}fetch()</script></body>
</html>

运行 node start.js,访问 http://localhost:3000

正常超时

正常情况下,浏览器发送请求,超过设置的时间后,axios 就会主动中断请求。

F12 开发人员工具的网络面板中可以看到,请求状态为 canceled(已取消)。

在这里插入图片描述

竞态场景

实际场景下,页面中经常会有多个请求同时发起,而不同浏览器也会限制同一时间处理请求的最大数量。这就会产生竞态,首先发起的请求就会被优先处理。超过上限的请求会强制挂起(pending),当前面的请求接收响应移出队列,腾出位置,挂起的请求才允许发送给服务器。

关键在于,请求挂起的过程中消耗的时间仍参与超时时间计算。

这就会有一些无法预料的超时场景,例如:

  • A请求耗时长,B在等待A的时候消耗过多时间,等到处理B请求的时候,时间所剩无几,还没等服务器响应,浏览器就主动中断了B请求
  • A请求耗时长,B在等待A的时候达到超时时间,浏览器中止B请求,可怜B请求的服务器什么都还没做
  • 等等

相同地址竞态

同一时间,浏览器只会处理同一地址的一个请求,其它的会挂起。

// public/index.html
const instance = axios.create({timeout: 8000 // 超过8秒超时,中止请求
})function fetch() {instance.get('/api/timeout')
}// 同时发起两个相同地址的请求
fetch()
fetch()

同时发起两个相同地址的请求,仅处理第一个,后面的会挂起,等待前面的请求结束

在这里插入图片描述

5秒后(如果只考虑服务器处理的时间)第一个接收响应(处理完成),轮到第二个,此时第二个的请求时间已经消耗了5秒

在这里插入图片描述

达到8秒时间上限,浏览器中止第二个请求。

在这里插入图片描述

同源不同地址竞态

浏览器允许同域名下多个不同地址的并发请求,但也设置了数量上限,例如 Chrome 上限为 6 个。

添加多个不同地址的5秒响应接口:

const express = require('express');const router = express.Router()router.get('/timeout', async (req, res, next) => {console.log('timeout')// 5 秒后响应setTimeout(() => {res.status(200).end('OK')}, 5000);
})router.get('/timeout2', async (req, res, next) => {console.log('timeout2')setTimeout(() => {res.status(200).end('OK')}, 5000);
})router.get('/timeout3', async (req, res, next) => {console.log('timeout3')setTimeout(() => {res.status(200).end('OK')}, 5000);
})router.get('/timeout4', async (req, res, next) => {console.log('timeout4')setTimeout(() => {res.status(200).end('OK')}, 5000);
})router.get('/timeout5', async (req, res, next) => {console.log('timeout5')setTimeout(() => {res.status(200).end('OK')}, 5000);
})router.get('/timeout6', async (req, res, next) => {console.log('timeout6')setTimeout(() => {res.status(200).end('OK')}, 5000);
})router.get('/timeout7', async (req, res, next) => {console.log('timeout7')setTimeout(() => {res.status(200).end('OK')}, 5000);
})router.get('/timeout8', async (req, res, next) => {console.log('timeout8')setTimeout(() => {res.status(200).end('OK')}, 5000);
})module.exports = router
// public/index.html
const instance = axios.create({timeout: 8000 // 超过8秒超时,中止请求
})function fetch(num) {instance.get('/api/timeout' + (num || ''))
}// 同一时间发送多个不同地址的请求
['',2,3,4,5,6,7,8].forEach(v => fetch(v))

同一时间向同域名下不同地址的接口发送请求,最多处理6个请求,其它的全部挂起

在这里插入图片描述

5秒后(如果只考虑服务器处理的时间)优先处理的6个请求接收响应(处理完成),挂起的请求进行补位,此时剩余接口的请求时间已经消耗了5秒

在这里插入图片描述

达到8秒时间上限,浏览器中止超时的请求。

在这里插入图片描述

不同源下地址竞态

浏览器对不同源下的请求不进行竞态,这就是使用 CDN 提高资源并行加载效率的原因。这里就不做示例了。

关于同源参考:浏览器的同源策略

总结

  • 前端设置的请求超时时间是从 JS 发起请求开始计算
  • 浏览器同一时间处理请求有数量上限,超过上限的请求将被挂起,等待处理队列空闲才会依次处理剩下的请求
  • 浏览器挂起的请求依然参与超时时间计算
  • 为避免请求在真正发送到服务器之前被浏览器消耗时间,可以使用 CDN 等不同源的请求地址,或定制超时重试机制。

http://chatgpt.dhexx.cn/article/awM1NOsL.shtml

相关文章

http请求响应状态为canceled

http请求响应状态为canceled问题 背景&#xff1a;vue3结合axios , 某个接口请求总是会出现canceled状态&#xff0c;如下图&#xff1a; 分析一下&#xff0c;可能是超时时间设置的问题&#xff0c;原始超时时间显示设置的是3s, 而这个接口响应时间大概有5&#xff5e;10s&a…

探究请求的接口响应status为canceled的原因

最近在和后端小伙伴调试接口的时候&#xff0c;有一个接口是响应status一直是canceled&#xff0c;导致接收不到数据或者说没有响应值返回&#xff0c;后端小伙伴看日志说是请求的数据已经返回了。正常的响应status应该是200&#xff0c;如果响应有误&#xff0c;响应的status应…

ajax表单提交造成请求canceled

表单提交中遇到了请求canceled问题 可以看到我们的button确认click事件是处于form表单内的, 当点击了button之后, form表单也有自己的默认表单提交事件, 这两个事件同时触发, from表单会将表单内容拼接到url后面, 导致页面重新加载, 会导致click事件中断,造成很长的延时, 所以出…

ItemTouchHelper.Callback 详解

ItemTouchHelper是在操作RecyclerView时&#xff0c;堆Item进行长按移动&#xff0c;左右滑动删除效果的一个辅助类&#xff0c;但是我们要考虑&#xff0c;为什么这个辅助类就可以实现移动跟左右删除Item的效果呢&#xff1f;我们的touch事件是怎么作用到RecyclerView的Item上…

JavaScript中的回调函数(callback)

前言 callback&#xff0c;大家都知道是回调函数的意思。如果让你举些callback的例子&#xff0c;我相信你可以举出一堆。但callback的概念你知道吗&#xff1f;你自己在实际应用中能不能合理利用回调实现功能&#xff1f; 我们在平时的学习中容易犯不去深究的病&#xff0c;功…

scrapy.Request callback不执行

上一篇博客介绍了Scrapy Post Request payload数据的问题&#xff0c;本篇记录一下scrapy.Request callback不执行的问题。 1、大家都说的解决方式&#xff0c;虽然没有解决我的问题&#xff0c;但是还是写到这里&#xff0c;算是一个总结&#xff1a; 1.在scrapy.Request方法里…

UVM: callback机制 uvm_callback和uvm_callbacks

callback机制 callback机制提高代码的可重用性&#xff0c;还用于构建异常的测试用例。 广义的callback机制有post_randomize()&#xff0c;pre_body(),post_body(), pre_do(), mid_do()等&#xff0c;它们提供了额外的接口给用户。 原理 以在driver中提供callback函数接口为…

SV和UVM的Callback例程

文章目录 前言一、SystemVerilog Callback例程二、UVM Callback例程总结 前言 记录SV和UVM的两个callback的例程&#xff0c;方便以后用的时候进行查阅。 一、SystemVerilog Callback例程 二、UVM Callback例程 总结 记录SV和UVM的callback例程。

ajax中的callback,ajax callback是什么

ajax的callback是什么? callback是ajax中的回调函数,是在服务器对一个请求对象作出响应时调用的函数。浏览器会在某个时刻”回调”这个函数,根据5种返回状态的情况处理ajax请求结果。 callback回调函数怎么理解? 想弄明白回调函数,首先的清楚地明白函数的规则。在javascri…

通俗易懂的讲解回调函数,保证让你看懂callback

什么是回调函数&#xff1f;相信很多人都似懂非懂&#xff0c;半懂不懂&#xff0c;今天就通俗易懂的讲解回调函数&#xff0c;让你能理解回调函数的大部分作用及意义。 目录 定义 形象的例子 代码解释 用处及完整代码例子 定义 先上常规的定义&#xff1a; 回调函数也是…

callback(回调函数)

先讲点题外话。 编程分为两类&#xff1a;系统编程&#xff08;system programming&#xff09;和应用编程&#xff08;application programming&#xff09;。所谓系统编程&#xff0c;简单来说&#xff0c;就是编写库&#xff1b;而应用编程就是利用写好的各种库来编写具某种…

Callback回调函数介绍(C语言)

目录 1. 回调函数的定义 2. 为什么要用回调函数 3. 怎么用回调函数 3.1 怎么使用没有参数的回调函数 3.2 怎么使用带参数的回调函数 1. 回调函数的定义 最近在工作中经常用到回调函数callback&#xff0c;总结一下。 先来看看维基百科对callback的解释&#xff1a;In co…

Callback函数详解

http://shiwawa.blog.hexun.com/9925417_d.html 一,回调函数 我们经常在C++设计时通过使用回调函数可以使有些应用(如定时器事件回调处理、用回调函数记录某操作进度等)变得非常方便和符合逻辑,那么它的内在机制如何呢,怎么定义呢?它和其它函数(比如钩子函数)有何不同呢…

《软件质量保证与测试》学习笔记【第一章 软件测试基本概念】

目录 前言为什么要进行软件测试什么是软件缺陷1.1 什么是软件测试1.2 软件测试与CMMI软件质量保证SQA与软件测试的关系 1.3测试用例1.3.1什么是测试用例测试用例的五大要素测试用例1.3.2测试用例的评价标准1.3.3测试用例设计的基本原则1.3.4测试用例模板 1.4测试环境1.4.1什么是…

群晖NAS教程(十)、利用Docker安装蚂蚁笔记(leanote)

为了更好的浏览体验,欢迎光顾勤奋的凯尔森同学个人博客 群晖NAS教程(十)、利用Docker安装蚂蚁笔记(leanote) 蚂蚁笔记是一款特别棒的笔记软件,支持Markdown语法,是程序员必备的软件之一。下面我们就在群晖DS918+的机器上docker出来一个耍耍。 一、下载蚂蚁笔记(leanote)镜…

基于 Qt 框架的开源笔记软件 VNote

关注、星标公众号&#xff0c;直达精彩内容 来源&#xff1a;OSC开源社区 作者&#xff1a;tamlok VNote是一个受Vim启发开发的专门为Markdown而优化、设计的笔记软件。 授权协议&#xff1a;MIT 开发语言&#xff1a;C/C JavaScript HTML/CSS SHELL 操作系统&#xff1a;跨平台…

VisionPro软件笔记

VisionPro笔记 1、CogPMAlignTool的操作方法&#xff1a; 抓取图像-设置训练区域及参数-训练模板-设置运行参数与区域-运行-查看结果 2、CogPMAlignTool的基本原理&#xff1a; 图案位置搜索工具&#xff08;识别定位&#xff09;基于边缘特征的模板而不是基于像素的模板匹配…

一款开源的支持离线的支持MarkDown的优秀笔记软件----思源笔记

日常工作中&#xff0c;大家可能会用笔记软件记录自己积累的一些知识&#xff0c;组建自己的知识管理系统&#xff0c;常用的工具可能有云笔记&#xff0c;如有道云笔记&#xff0c;印象笔记等&#xff0c;但是有时候在工作中&#xff0c;信息比较敏感&#xff0c;不能够将信息…

一文了解常用效率记笔记软件(超过20款含有图片和双向链笔记)

前言 Mac 软件推荐下载网址 麦软网&#xff1a;https://www.macfz.com腾讯柠檬&#xff1a;https://lemon.qq.com/lab 更新时间 第七次更新 6 月 28 号 &#xff0c;对于有道和印象的理解&#xff0c;有时间把这篇文章拆分下第六次更新 5 月 27 号&#xff0c;更新了如何看待…

知识管理软件,有道云笔记的优缺点和C笔记

前言 软件有道云笔记C笔记发布时间2011年6月28日还在内测所属公司网易公司北京创新乐知网络技术有限公司 1.笔记的重要性&#xff1a; 大家有没有一种种感受&#xff0c;我们成日钻研书籍&#xff0c;天天认真听讲&#xff0c;发奋学习&#xff0c;收到的反馈却并不理想&…