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

在async函数中加载脚本导致display_page无法执行的问题

问题分析与修复:await load_scripts后display_page无法执行的问题

你遇到的核心问题:在异步函数f1中,给load_scripts()加await时,后续的display_page()完全不执行;但去掉await的话,display_page()会执行,却无法满足「脚本加载完成后再显示页面」的需求。

你的代码如下:

const loading = document.getElementById('loading_screen')
const page = document.getElementById('main')

function hide_page() {
  console.log('1')
  loading.style.display = 'block'
  loading.style.opacity = '1'
  loading.addEventListener('transitionend', () => {
    page.style.display = 'none'
  })

  return new Promise((resolve) => {
    loading.ontransitionend = resolve
  })
}

function display_page() {
  console.log('2')
  page.style.display = 'flex'
  loading.style.opacity = '0'
  loading.addEventListener('transitionend', () => {
    loading.style.display = 'none'
  })

  return new Promise((resolve) => {
    loading.ontransitionend = resolve
  })
}

function load_scripts(files) {
  var promises = []
  files.forEach((src) => {
    let script = document.createElement("script")
    script.setAttribute('type', 'text/javascript')
    script.setAttribute('class', 'local_script')
    script.async = false;
    script.setAttribute('src', src)
    document.getElementById('head').appendChild(script)
    promises.push(new Promise((resolve) => {
      script.onload = resolve
      script.onerror = resolve
    }));
  })
  return Promise.all(promises)
}

async function f1() {
  await hide_page()
  await load_scripts(some_scripts_urls);
  // load_scripts(some_scripts_urls); //此方式可执行display_page,但脚本会后执行,不符合需求
  await display_page();
  console.log('3')
}
f1()

问题根源

  1. load_scripts的Promise可能永久pending
    设置script.async = false后,脚本按顺序同步加载,但如果脚本URL错误、存在跨域问题,或者浏览器缓存导致onload/onerror事件不触发,对应的Promise就永远不会resolve,导致await load_scripts卡住,后续代码无法执行。

  2. 过渡事件绑定逻辑冲突
    hide_page和display_page同时使用addEventListener和ontransitionend赋值(后者会覆盖前者的事件处理函数),且未移除监听,可能导致过渡事件触发逻辑混乱,影响Promise的resolve。


修复方案

1. 修复load_scripts的Promise触发逻辑

兼容所有加载场景,确保每个脚本的Promise都能正常resolve:

function load_scripts(files) {
  var promises = []
  files.forEach((src) => {
    promises.push(new Promise((resolve) => {
      let script = document.createElement("script")
      script.type = 'text/javascript'
      script.className = 'local_script'
      script.async = false;
      script.src = src

      // 统一处理加载完成/失败的逻辑
      const finish = () => {
        // 移除事件监听避免重复触发
        script.onload = null
        script.onerror = null
        script.onreadystatechange = null
        resolve()
      }

      script.onload = finish
      script.onerror = finish
      // 兼容IE等老浏览器的状态变化
      script.onreadystatechange = () => {
        if (['loaded', 'complete'].includes(script.readyState)) {
          finish()
        }
      }

      document.getElementById('head').appendChild(script)
    }));
  })
  return Promise.all(promises)
}

2. 修复过渡事件处理逻辑

确保过渡事件只触发一次,且Promise能正确resolve:

function hide_page() {
  console.log('1')
  // 重置状态+触发重绘,确保过渡能正常触发
  loading.style.display = 'none'
  loading.offsetHeight // 强制浏览器重绘,识别状态变化
  loading.style.display = 'block'
  loading.style.opacity = '1'

  return new Promise((resolve) => {
    const onTransitionEnd = (e) => {
      // 确保只监听opacity的过渡结束事件
      if (e.propertyName === 'opacity') {
        page.style.display = 'none'
        loading.removeEventListener('transitionend', onTransitionEnd)
        resolve()
      }
    }
    loading.addEventListener('transitionend', onTransitionEnd)
  })
}

function display_page() {
  console.log('2')
  page.style.display = 'flex'
  // 重置loading状态+触发重绘
  loading.style.display = 'block'
  loading.offsetHeight
  loading.style.opacity = '0'

  return new Promise((resolve) => {
    const onTransitionEnd = (e) => {
      if (e.propertyName === 'opacity') {
        loading.style.display = 'none'
        loading.removeEventListener('transitionend', onTransitionEnd)
        resolve()
      }
    }
    loading.addEventListener('transitionend', onTransitionEnd)
  })
}

3. 优化f1函数的容错性

添加错误捕获,避免脚本加载失败导致整个流程卡住:

async function f1() {
  await hide_page()
  try {
    await load_scripts(some_scripts_urls);
  } catch (err) {
    console.error('脚本加载失败:', err)
  }
  await display_page();
  console.log('3')
}
f1()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 12:10:38