为何所有文件加载成功后网站仍显示加载图标?Promise相关问题
问题原因
- 核心问题出在
document.write的调用时机:你在异步的async函数中调用document.write,此时浏览器初始的文档加载流程已经结束,document.write会隐式触发document.open()开启新的文档流,而你没有手动调用document.close()关闭文档流,浏览器会默认认为文档还在加载中,所以加载图标一直不会消失。 - 次要问题:你把脚本放在
head标签内直接执行,没有等待DOM加载完成,虽然你的场景没有触发报错,但属于不规范的写法。
修复方案
方案1:替换document.write为标准DOM操作(更推荐)
修改controller.js的代码,直接向body插入内容,不需要操作文档流,也不会触发加载状态异常:
function myDisplayer(some) { document.body.innerHTML = some; } async function loadController(){ let myPromise = new Promise(function(myResolve, myReject) { let req = new XMLHttpRequest(); req.open('GET', "controllerDummy.html"); req.onload = function() { if (req.status == 200) { myResolve(req.response); } else { myReject("File not Found"); } }; req.send(); }); myDisplayer(await myPromise); } // 等待DOM加载完成再执行,避免body未初始化报错 document.addEventListener('DOMContentLoaded', loadController)
方案2:保留document.write,手动关闭文档流
如果要保留原来的写法,只需要在document.write后追加关闭文档流的逻辑即可:
function myDisplayer(some) { document.write(some); document.close(); // 手动关闭文档流,通知浏览器加载完成 }
原有实现是否过时?
是,目前已经有更简洁的标准实现方式:
- 网络请求可以直接用
fetchAPI,原生支持Promise,不需要手动封装XMLHttpRequest,配合async/await语法非常简洁:
async function loadController(){ try { const res = await fetch('controllerDummy.html') if(!res.ok) throw new Error('File not Found') const content = await res.text() document.body.innerHTML = content } catch (err) { console.error(err) } } document.addEventListener('DOMContentLoaded', loadController)
document.write属于非常早期的DOM操作API,现在已经不推荐使用,尤其是异步场景下很容易触发各种奇怪的问题,优先使用innerHTML或者appendChild等标准DOM操作方法。
内容的提问来源于stack exchange,提问作者MoulikChawla
相关产品推荐
相关产品推荐

