欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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"));