document.write 和 异步
程序员文章站
2022-06-04 16:58:01
...
今天碰到一个大坑,分享一下。
项目中首页用了一个什么安全联盟标志,具体用处不大,就是逼格显得高一点点。我们原来是这么用的。
<a key ="" logo_size="124x47" logo_type="business" href="http://www.anquan.org">
<script src="//static.anquan.org/static/outer/js/aq_auth.js"></script>
</a>
然后今天突然发现,这个js加载需要30多秒,直接阻塞了之后的html以及js加载。整个页面就在那儿白屏了整整30多秒,然后才加载了出来。(还好这是一个首页,说实话平时浏览的人不是特别多,但是也算是重要门户,后来紧急先把这个功能先下了)
大家讨论了一下,这种外部引用又不算是特别重要的东西,一定要用异步。
坑又来了,这段js代码,中间用了document.write,异步加载写不进去东西直接报错。
尝试了以下几种方案:
1、在script标签直接加上async="true"
2、在页面末尾位置将这个a标签直接append进去(首页有很多动画效果,引用过jquery)
3、script标签不加src,而是在js中动态加载src
以上方法都是异步方法。均直接报错。
后来找到了一种方法:
让document.write的广告无阻塞的加载 - 雨夜带刀
这篇文章使用了一种方法,利用textarea的延迟渲染和对document.write的重写,实现异步配合document.write的方案。
// html部分
<a key ="" logo_size="124x47" logo_type="business" href="http://www.anquan.org">
<textarea id="aTextarea" style="display:none">
<script src="//static.anquan.org/static/outer/js/aq_auth.js"></script>
</textarea>
</a>
// js部分
var loadScript = function( elem ){
var url = elem.value.match( /src="([\s\S]*?)"/i )[1],
parent = elem.parentNode,
docWrite = document.write, // 缓存原生的document.write
script = document.createElement('script'), // 创建一个新script来加载
head = document.head || document.getElementsByTagName('head')[0] || document.documentElement;
// 重写document.write
document.write = function(text){
parent.innerHTML = text;
};
script.type = 'text/javascript';
script.src = url;
script.onerror =
script.onload =
script.onreadystatechange = function(e){
e = e || window.event;
if(!script.readyState || /loaded|complete/.test(script.readyState) || e === 'error'){
// 恢复原生的document.write
document.write = docWrite;
head.removeChild(script);
// 卸载事件和断开DOM的引用
// 尽量避免内存泄漏
head =
parent =
elem =
script =
script.onerror =
script.onload =
script.onreadystatechange = null;
}
};
// 加载script
head.insertBefore(script, head.firstChild);
};
loadScript(document.getElementById("aTextarea"));
上一篇: 两则简单面试题