Chrome为何在简单页面中延迟发送Ajax请求?
嘿,这个问题问到点子上了!看起来简单的HTML背后,Chrome其实在默默完成不少初始化工作,我来帮你拆解这段180ms左右的时间里浏览器在做什么,以及怎么让请求发送得更早~
一、Chrome在HTML下载完成到发送请求之间的核心操作
哪怕是你写的这种极简HTML,浏览器的处理流程也有几个关键步骤,加起来就产生了这段延迟:
- HTML解析与DOM初始化:浏览器收到HTML字节后,首先要把它转换成可识别的令牌(比如
<html>、<script>这些标签),再构建初始的DOM树。这个过程看似简单,但浏览器的解析器本身需要初始化,加上要处理文档声明、编码这些基础信息,会占用一点时间。 - 脚本的编译与准备:当解析到
<head>里的内联脚本时,浏览器会暂停DOM解析,把代码交给V8引擎。V8需要先完成自身的初始化(如果是页面的第一个脚本,这一步的开销会更明显),然后对代码做语法解析、生成抽象语法树,最后编译成可执行的字节码。 - 异步任务的调度:
fetch()是异步的宏任务,当你在脚本里调用它时,浏览器不会立刻发送请求——它会先把这个请求任务加入到事件循环的队列里,等当前同步脚本执行完毕后,才会调度网络线程去处理这个请求。另外,网络线程本身也需要完成初始化调度,比如检查跨域规则、分配请求资源,这些都需要一点时间。 - 预加载扫描器的局限性:浏览器有个预加载扫描器,会提前抓取HTML里的资源(比如
<link>、<img>),但它没法识别内联脚本里的fetch调用,所以没法提前帮你发起这个请求。
二、让请求更早发送的优化方法
要缩短这段延迟,最有效的办法是利用浏览器的预加载机制,或者调整脚本的执行时机:
- 用
<link rel="preload">提前声明请求:这是最直接的方式,预加载扫描器会在HTML解析的初期就识别这个标签,立刻发起请求,之后你的fetch调用会直接复用已经发起的请求结果。修改后的代码如下:<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <!-- 提前预加载请求 --> <link rel="preload" href="https://www.google.com" as="fetch"> <script> const jsonPromise = fetch("https://www.google.com"); jsonPromise.then(() => alert("done")); </script> </head> <body> </body> </html> - 避免不必要的阻塞:如果你的脚本不需要依赖DOM,可以把它放在
<body>标签的末尾,不过这对fetch的发送时机影响不大,因为脚本还是要等DOM解析到它才会执行。更关键的是预加载,能让请求发起时间大幅提前。
另外要注意:如果你的HTML是通过file://协议本地打开的,浏览器会做更多安全上下文的检查,初始化开销会比从HTTP服务器加载更大,延迟也会更明显。
内容的提问来源于stack exchange,提问作者user746461
相关产品推荐
相关产品推荐

