0

0

优化Web性能:使用异步XHR与Fetch API获取文件修改时间

聖光之護

聖光之護

发布时间:2025-08-16 22:44:28

|

802人浏览过

|

来源于php中文网

原创

优化Web性能:使用异步XHR与Fetch API获取文件修改时间

本文详细介绍了如何将同步XMLHttpRequest请求转换为异步模式,以避免阻塞主线程并提升用户体验。通过XMLHttpRequest的事件监听机制和现代Fetch API,我们将展示如何高效、非阻塞地获取服务器端文件的最后修改时间,并实现页面根据文件状态自动刷新,同时提供示例代码和最佳实践。

1. 同步XMLHttpRequest的问题与危害

在web开发中,通过javascript与服务器进行数据交互是常见的需求。xmlhttprequest(xhr)是实现这一功能的核心api之一。然而,当xhr请求设置为同步模式(即req.open("head", url, false);中的第三个参数为false)时,它会阻塞浏览器的主线程,直到请求完成。这意味着在请求期间,用户界面将变得无响应,无法滚动、点击或执行任何其他操作,严重损害用户体验。现代浏览器普遍对此行为发出警告,并强烈建议避免在主线程中使用同步xhr。

原始的同步请求代码示例如下,它用于获取文件最后修改时间并计算其与当前时间的时间差:

       

尽管这段代码能实现功能,但其同步特性会导致页面卡顿,尤其是在网络条件不佳或请求频率较高时。浏览器控制台通常会给出类似“Synchronous XMLHttpRequest on the main thread is deprecated...”的警告。

2. 异步XMLHttpRequest的实现

要解决同步XHR带来的问题,核心在于将其转换为异步模式。异步请求不会阻塞主线程,而是通过回调函数或事件监听器在请求完成后通知我们。

2.1 异步XHR原理

异步XHR通过以下两种方式处理响应:

  • onreadystatechange 事件: 这是一个较旧但仍有效的方法。当readyState属性发生变化时触发,当readyState达到XMLHttpRequest.DONE(4)时,表示请求已完成。
  • addEventListener('load') 事件: 这是更推荐的现代方法,当XHR请求成功完成时触发。它更简洁,并且只关注请求成功的最终状态。

2.2 异步XHR代码示例

以下是将原同步XHR代码转换为异步的实现,它利用addEventListener('load')来处理响应:

const pageload = new Date(); // 页面加载时间
const url = "Akut.txt"; // 目标文件URL
const whichHeader = "Last-Modified"; // 要获取的响应头

// 比较时间并更新UI的函数
const compareTimeToNow = (time) => {
  let d = new Date();
  let diffSec = Math.round((d - time) / 1000);
  document.getElementById("time").textContent = Math.trunc(diffSec / 60) + " minutes"; // 显示自修改以来的分钟数

  // 如果页面加载超过10秒且文件在5秒内被修改过,则刷新页面
  if ((d - pageload) / 1000 > 10 && diffSec < 5) {
    location.reload();
  } else {
    // 请求完成后,等待2.5秒再次发起请求,形成周期性检查
    setTimeout(getHeader, 2500); 
  }
};

// XHR请求完成时的监听器
function reqListener() {
  // console.log(this.responseText); // HEAD请求通常responseText为空
  // 从响应头获取'Last-Modified'时间,并转换为Date对象,然后传递给compareTimeToNow
  compareTimeToNow(new Date(this.getResponseHeader(whichHeader)).getTime());
}

// 发起HEAD请求的函数
const getHeader = () => {
  const req = new XMLHttpRequest();
  req.addEventListener("load", reqListener); // 监听load事件
  req.open("HEAD", url); // 异步请求,默认第三个参数为true
  req.send();
};

// 首次调用以启动周期性检查
getHeader();

代码解析:

Removal.AI
Removal.AI

AI移出图片背景工具

下载
  • req.open("HEAD", url);:第三个参数默认为true,表示异步请求。
  • req.addEventListener("load", reqListener);:当请求成功加载时,reqListener函数会被调用。
  • reqListener函数内部:通过this.getResponseHeader(whichHeader)获取所需的Last-Modified头信息,并将其转换为时间戳传递给compareTimeToNow函数。
  • 周期性检查:这里不再使用setInterval,而是采用setTimeout。在compareTimeToNow函数中,每次处理完数据后,如果不需要刷新页面,就调用setTimeout(getHeader, 2500)来调度下一次请求。这种模式可以确保前一个请求完全完成后才发起下一个请求,避免了请求重叠和资源竞争的问题,尤其适用于请求时间不确定的场景。

3. 使用Fetch API的现代方法

Fetch API是现代Web开发中进行网络请求的推荐方式,它基于Promise,提供了一种更强大、更灵活、更简洁的API来替代XMLHttpRequest。Fetch API的使用可以进一步简化代码,并提供更好的错误处理机制。

3.1 Fetch API的优势

  • 基于Promise: 使得异步代码的编写更加直观,避免了回调地狱。
  • 更简洁的语法: 相较于XHR,Fetch API的链式调用使得代码更易读。
  • 更强大的功能: 支持更多HTTP特性,如CORS、流式响应等。

3.2 Fetch API代码示例

以下是使用Fetch API实现相同功能的代码:

const pageload = new Date(); // 页面加载时间
const url = "Akut.txt"; // 目标文件URL
const whichHeader = "Last-Modified"; // 要获取的响应头

// 比较时间并更新UI的函数(与XHR版本相同)
const compareTimeToNow = (time) => {
  let d = new Date();
  let diffSec = Math.round((d - time) / 1000);
  document.getElementById("time").textContent = Math.trunc(diffSec / 60) + " minutes"; // 显示自修改以来的分钟数

  if ((d - pageload) / 1000 > 10 && diffSec < 5) {
    location.reload();
  } else {
    setTimeout(getHeader, 2500); // 周期性调度下一次请求
  }
};

// 发起Fetch请求的函数
const getHeader = () => {
  fetch(url, { method: 'HEAD' }) // 发起HEAD请求
  .then(rsp => {
    // 获取响应头,并转换为时间戳传递给compareTimeToNow
    compareTimeToNow(new Date(rsp.headers.get(whichHeader)).getTime());
  })
  .catch(error => {
    console.error("Fetch请求失败:", error);
    // 失败后也应考虑是否继续调度下一次请求,例如延迟重试
    setTimeout(getHeader, 5000); // 失败后延迟更久重试
  });
};

// 首次调用以启动周期性检查
getHeader();

代码解析:

  • fetch(url, { method: 'HEAD' }):发起一个HEAD请求。默认是GET请求,需要通过method选项指定。
  • .then(rsp => { ... }):当请求成功并接收到响应时,Promise会解析,并提供一个Response对象rsp。
  • rsp.headers.get(whichHeader):通过Response对象的headers属性(一个Headers对象)来获取指定的响应头。
  • .catch(error => { ... }):用于捕获网络错误或请求失败的情况,提供了健壮的错误处理机制。

4. 注意事项与最佳实践

  • 错误处理: 无论是XHR还是Fetch,都应加入适当的错误处理逻辑。对于XHR,可以在addEventListener('error', handler)或addEventListener('abort', handler)中处理;对于Fetch,使用.catch()方法捕获Promise的拒绝状态。
  • 周期性检查的优化:
    • setTimeout vs setInterval: 在需要周期性执行异步操作时,通常推荐使用setTimeout递归调用自身,而不是setInterval。这是因为setInterval会不顾前一个任务是否完成就启动下一个任务,可能导致任务堆叠或资源耗尽。而setTimeout则确保了前一个任务完成后才调度下一个任务。
    • 动态间隔: 如果文件修改不频繁,可以考虑根据文件的修改频率动态调整检查间隔,或者在服务器端提供更高效的通知机制(如WebSocket或Server-Sent Events)。
  • 浏览器兼容性: Fetch API在现代浏览器中得到了广泛支持(Chrome 42+, Edge 14+, Safari 10.1+, Firefox 39+, Opera 29+),但不支持IE。如果需要兼容IE浏览器,则必须使用异步XMLHttpRequest。
  • 服务器负载: 频繁地向服务器发送HEAD请求,即使请求本身很轻量,也可能对服务器造成不必要的负载。在生产环境中,应仔细评估其影响。
  • 替代方案: 对于需要高实时性的场景,轮询(Polling)通常不是最佳选择。可以考虑以下替代方案:
    • WebSockets: 提供全双工通信,服务器可以在文件修改时主动推送消息给客户端。
    • Server-Sent Events (SSE): 允许服务器单向推送数据到客户端,适用于服务器事件驱动的更新。

总结

将同步XMLHttpRequest请求转换为异步模式是优化Web性能的关键一步,它能有效避免主线程阻塞,提升用户体验。通过XMLHttpRequest的事件监听器或更现代、更强大的Fetch API,我们可以轻松实现非阻塞的网络请求。在选择具体实现方式时,应根据项目需求、浏览器兼容性以及对代码简洁性的偏好进行权衡。同时,对于周期性任务,采用setTimeout递归调用而非setInterval,并结合适当的错误处理,是构建健壮Web应用的最佳实践。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
chrome什么意思
chrome什么意思

chrome是浏览器的意思,由Google开发的网络浏览器,它在2008年首次发布,并迅速成为全球最受欢迎的浏览器之一。本专题为大家提供chrome相关的文章、下载、课程内容,供大家免费下载体验。

864

2023.08.11

chrome无法加载插件怎么办
chrome无法加载插件怎么办

chrome无法加载插件可以通过检查插件是否已正确安装、禁用和启用插件、清除插件缓存、更新浏览器和插件、检查网络连接和尝试在隐身模式下加载插件方法解决。更多关于chrome相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

748

2023.11.06

edge是什么浏览器
edge是什么浏览器

Edge是一款由Microsoft开发的网页浏览器,是Windows 10操作系统中默认的浏览器,其目标是提供更快、更安全、更现代化的浏览器体验。本专题为大家提供edge浏览器相关的文章、下载、课程内容,供大家免费下载体验。

1449

2023.08.21

IE浏览器自动跳转EDGE如何恢复
IE浏览器自动跳转EDGE如何恢复

ie浏览器自动跳转edge的解决办法:1、更改默认浏览器设置;2、阻止edge浏览器的自动跳转;3、更改超链接的默认打开方式;4、禁用“快速网页查看器”;5、卸载edge浏览器;6、检查第三方插件或应用程序等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

382

2024.03.05

如何解决Edge打开但没有标题的问题
如何解决Edge打开但没有标题的问题

若 Microsoft Edge 浏览器打开后无标题(窗口空白或标题栏缺失),可尝试以下方法解决: 重启 Edge:关闭所有窗口,重新启动浏览器。 重置窗口布局:右击任务栏 Edge 图标 → 选择「最大化」或「还原」。 禁用扩展:进入 edge://extensions 临时关闭插件测试。 重置浏览器设置:前往 edge://settings/reset 恢复默认配置。 更新或重装 Edge:检查最新版本,或通过控制面板修复

948

2025.04.24

scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

228

2023.10.18

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

298

2023.10.25

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

398

2023.07.18

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

54

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
如何进行WebSocket调试
如何进行WebSocket调试

共1课时 | 0.1万人学习

TypeScript全面解读课程
TypeScript全面解读课程

共26课时 | 5.1万人学习

前端工程化(ES6模块化和webpack打包)
前端工程化(ES6模块化和webpack打包)

共24课时 | 5.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号