You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将获取文件Last-Modified的同步XMLHttpRequest改为异步?

异步改造XMLHttpRequest实现文件修改检测

问题背景

原同步代码可获取服务器文件Last-Modified时间,实现文件修改检测、自动刷新页面和显示修改后时长,但存在两个问题:

  • 浏览器抛出「主线程同步XMLHttpRequest已废弃」警告
  • 多窗口运行时会导致电脑卡顿

尝试改为异步版本后无法正确获取Last-Modified时间,返回NaN,需要完成异步改造。

原同步代码

<script>
    var pageload = new Date();
    function fetchHeader(url, wch) {
        try {
            var req=new XMLHttpRequest();
            req.open("HEAD", url, false);
            req.send(null);
            if(req.status== 200){
                return req.getResponseHeader(wch);
            }
            else return false;
        } catch(er) {
            return er.message;
        }
    }

    window.setInterval(function(){
        var time = Date.parse(fetchHeader("Akut.txt",'Last-Modified'));
        var d = new Date();
        var diffSec = Math.round((d - time) / 1000);
        document.getElementById("time").innerHTML = Math.trunc(diffSec/60) + " minutes"; // time since it was modified
        
        if ((d-pageload)/1000 > 10 && diffSec < 5 ){
            location.reload();
        }
    }, 2500);
</script>

失败的异步尝试

<script>
    function fetchHeader(url, wch) {
        try {
            var xhr = new XMLHttpRequest()
            xhr.onreadystatechange = function() {
                if (this.readyState === this.DONE) {
                    console.log(this.getResponseHeader(wch)); // assumed this would work but it doesn't
                }
            }
            xhr.open("HEAD", url)
            xhr.send()
        } catch(er) {
            return er.message;
        }
    }
</script>

正确的异步改造方案

异步操作的核心是不能直接通过return返回结果,需要用Promise封装异步请求,再通过async/await处理异步流程:

1. 封装异步获取请求头的函数

function fetchHeader(url, wch) {
  return new Promise((resolve, reject) => {
    try {
      const xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function() {
        if (this.readyState === this.DONE) {
          if (this.status === 200) {
            resolve(this.getResponseHeader(wch));
          } else {
            resolve(false);
          }
        }
      };
      // 处理请求错误
      xhr.onerror = () => reject(new Error('请求文件信息失败'));
      xhr.open("HEAD", url);
      xhr.send();
    } catch (err) {
      reject(err.message);
    }
  });
}

2. 改造定时器逻辑

使用async/await等待异步请求结果,再执行后续的时间计算和页面刷新逻辑:

const pageload = new Date();

window.setInterval(async function() {
  try {
    const lastModifiedStr = await fetchHeader("Akut.txt", 'Last-Modified');
    // 处理请求失败或状态非200的情况
    if (!lastModifiedStr) return;
    
    const time = Date.parse(lastModifiedStr);
    // 处理时间解析失败的情况
    if (isNaN(time)) {
      console.error('解析Last-Modified时间失败');
      return;
    }
    
    const d = new Date();
    const diffSec = Math.round((d - time) / 1000);
    document.getElementById("time").innerHTML = Math.trunc(diffSec / 60) + " minutes";
    
    // 判断是否需要刷新页面
    if ((d - pageload) / 1000 > 10 && diffSec < 5) {
      location.reload();
    }
  } catch (err) {
    console.error('获取文件信息出错:', err);
  }
}, 2500);

改造说明

  • 之前的异步代码失败原因:fetchHeader没有返回值,异步请求的结果无法被定时器中的代码获取,导致Date.parse接收不到有效参数返回NaN
  • 用Promise封装异步请求后,通过await可以在定时器中等待请求完成,确保拿到有效结果后再执行后续逻辑
  • 增加了错误处理,避免单个请求失败导致整个逻辑崩溃

内容的提问来源于stack exchange,提问作者Andreas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 16:05:34