write完结无阻塞加载js广告,write输出的广告无阻

时间:2019-07-28 09:27来源:2020欧洲杯冠军竞猜官方网站
 script.type = 'text/javascript';  script.src = url;             if(script.readyState) {//IE                 script.onreadystatechange = function() {                     if(script.readyState ==

 script.type = 'text/javascript';
 script.src = url;

            if(script.readyState) {//IE
                script.onreadystatechange = function() {
                    if(script.readyState == "loaded" || script.readyState == "complete") {
                        script.onreadystatechange = null;
                        _this.startNext();
                    }
                };
            } else {//Other
                script.onload = function() {
                    _this.startNext();
                };
            }
            //重写document.write
            document.write = function(ad) {
                var html = _this.containerObj.innerHTML;
                _this.containerObj.innerHTML = html ad;
            }

复制代码 代码如下:

            _this.init.apply();

四、图片延迟加载的增强版

        this.callback = callback ||
        function() {
        };

 script.onerror =
 script.onload =
 script.onreadystatechange = function( e ){
  e = e || window.event;
  if( !script.readyState ||
  /loaded|complete/.test(script.readyState) ||
  e === 'error'
  ){

var loadScript = ( function() {
    var adQueue = [], dw = document.write;
    //缓存js自身的document.write

 // 加载script
 head.insertBefore( script, head.firstChild );
};

//ad2.js
document.write('<img src="" width="270" height="129" usemap="#mp">');

一、广告代码分析

第一版本的问题是在多个文件调用的时候,会出现一些问题:
1. 由于文件加载的速度不一样,导致可能有些先加载有些后加载,也就是无序的,而且很多时候我们需要的是有序的。比如我们需要先加载第一屏的广告。

二、重写document.write

            script.src = _this.url;
            script.type = 'text/javascript';
            document.getElementsByTagName('head')[0].appendChild(script);
        },
        finished : function() {
            //还原document.write
            document.write = this.dw;
        },
        startNext : function() {
            adQueue.shift();
            this.callback.apply();
            if(adQueue.length > 0) {
                adQueue[0].startLoad();
            } else {
                this.finished();
            }
        }
    };

   // 卸载事件和断开DOM的引用
   // 尽量避免内存泄漏
   head =    
   parent =
   elem =
   script =
   script.onerror =
   script.onload =
   script.onreadystatechange = null;

上边都是大家熟悉的,看过书的同学都知道这样无阻塞加载的好处,效果挺不错的,当此等无阻塞脚本遇到一般js广告就来了写问题——广告代码出现在HTML里面了却不显示广告。
纳尼?HTML出来了不渲染到页面上?
先看看广告js代码
document.write('<img src="" alt="Logo">');
代码挺简单就一个document.write输出HTML代码(相信很多广告商的广告都这样),页面不显示广告问题在哪里呢? 问题就在这个document.write。为什么?先w3schools看看document.write的定义很使用吧。
定义和用法
write() 方法可向文档写入 HTML 表达式或 JavaScript 代码。
可列出多个参数(exp1,exp2,exp3,...) ,它们将按顺序被追加到文档中。
方法:
一是在使用该方在文档中输出 HTML,另一种是在调用该方法的的窗口之外的窗口、框架中产生新文档。在第二种情况中,请务必使用 close() 方法来关闭文档。
但其原理是在页面流输入过程中执行,一旦页面加载完毕,再次调用 document.write(),会隐式地调用 document.open() 来擦除当前文档并开始一个新的文档。也就是说如果在HTML加载完后我们再使用document.write会檫除之前生成html,而显示document.write输出的内容。
而我们例子中在页面加载完后在在html中输出document.write,就不会被执行了。问题知道了,原理知道了,那怎么解决这个问题呢?
异步利用ajax,行不同,很多广告文件都是第三方的,在不同域名下,存在跨域问题,而且不能我们控制其代码的输出。在这种情况下我们想到了一个办法就是重写掉document.write,在js文件加载结束后再把document.write重写回去。看代码。
第一版本无阻塞加载js广告:
    function LoadADScript(url, container, callback){
        this.dw = document.write;
        this.url = url;
        this.containerObj = (typeof container == 'string'?document.getElementById(container):container);
        this.callback = callback || function(){};
    }
   
    LoadADScript.prototype = {
        startLoad: function(){
            var script = document.createElement('script'),
                _this = this;
           
            if(script.readyState){ //IE
                script.onreadystatechange = function(){
                if (script.readyState == "loaded" || script.readyState == "complete"){
                    script.onreadystatechange = null;
                    _this.finished();
                }
            };
            }else{ //Other
                script.onload = function(){
                    _this.finished();
                };
            }
           
            document.write = function(ad){
                var html = _this.containerObj.innerHTML;
                _this.containerObj.innerHTML = html ad;
            }
           
            script.src = _this.url;
            script.type = 'text/javascript';
            document.getElementsByTagName('head')[0].appendChild(script);
        },
        finished: function(){
            document.write = this.dw;
            this.callback.apply();
        }
    };   

这个javascript请求返回的是这样的一段代码:

    return {
        add : function(adObj) {
            if(!adObj)
                return;

复制代码 代码如下:

页面调用代码:
    var loadScript = new LoadADScript('ad.js','msat-adwrap',function(){ console.log('msat-adwrap'); });
    loadScript.startLoad();
   
    var loadScript = new LoadADScript('ad2.js','msat-adwrap',function(){ console.log('msat-adwrap2'); });
    loadScript.startLoad();
   
    var loadScript = new LoadADScript('ad3.js','msat-adwrap',function(){ console.log('msat-adwrap3'); });
    loadScript.startLoad();

<div>
<textarea style="display:none">
<script type="text/javascript" src="
;ap=2EBE5681_1BA3_4663_FA3F_E73D2B83FBDC;ct=js;pu=5173;/?"></script>
</textarea>
</div>

//ad3.js
document.write('<img alt="Google" height="95" id="hplogo" src="" width="275">');

<script type="text/javascript" src="
;ap=2EBE5681_1BA3_4663_FA3F_E73D2B83FBDC;ct=js;pu=5173;/?"></script>

            adQueue.push(new LoadADScript(adObj.url, adObj.container, adObj.init, adObj.callback));
            return this;
        },
        execute : function() {
            if(adQueue.length > 0) {
                adQueue[0].startLoad();
            }
        }
    };
}());

  }
 }

无阻塞加载javascript,对于页面性能优化有很大的作用,这样能有效的减少js对页面加载的阻塞。特别是一些广告js文件,由于广告内容有可能是富媒体,更是很可能成为你页面加载提速的瓶颈,高性能javascript告诉我们,同学,提升你的网页速度,就无阻塞地加载JS吧。
于是便有一下代码出现。
(function() {
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = '';
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
})();

为了避免阻塞,就不能让document.write方法在页面渲染的时候执行,必须想办法让javascript的广告代码在DOM树就绪(DOM ready)之后才执行,但是在DOM树就绪后执行document.write会重新渲染整个页面,这样也是不行的。document.write虽然是浏览器原生的方法,但是也可以自定义一个方法来覆盖掉原来的方法。在javascript广告代码加载之前,重写document.write,等加载并执行完再改回来。

    function LoadADScript(url, container, init, callback) {
        this.url = url;
        this.containerObj = ( typeof container == 'string' ? document.getElementById(container) : container);
        this.init = init ||
        function() {
        };

您可能感兴趣的文章:

  • JavaScript中的无阻塞加载性能优化方案
  • Javascript无阻塞加载具体方式
  • 无阻塞加载js,防止因js加载不了影响页面显示的问题

摘自  红草帽

为了让javascript广告代码按顺序加载就需要一个队列来控制加载。于是又有了下面这段简单的队列控制代码:

...

图片延迟加载器请参阅比文://www.jb51.net/article/50685.htm 

广告js代码
//ad.js
document.write('<img src="" alt="Logo">');

2020欧洲杯冠军竞猜官方网站 1

loadscript.js源代码
/**
 * 无阻塞加载广告
 * @author Arain.Yu
 */

五、队列控制

    LoadADScript.prototype = {
        startLoad : function() {
            var script = document.createElement('script'), _this = this;

三、延迟加载javascript代码

  1. 想有些广告需要前置设置一些参数的,例如google adsense
     
    为了解决这两个问题好进一步修改成最终无阻塞加载js版本。
    HTML页面代码:
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8" />
            <title>new_file</title>
            <script type="text/javascript" src="loadscript.js"></script>
        </head>
    <body>
    <div id = "msat-adwrap"></div>
    <div id = "msat-adwrap2"></div>
    <script type="text/javascript">
        loadScript.add({
            url:'ad.js',
            container: 'msat-adwrap',
            callback:function(){ console.log('msat-adwrap'); }
        }).add({
            url:'ad2.js',
            container: 'msat-adwrap2',
            callback:function(){ console.log('msat-adwrap2'); }
        }).add({//google adsense
            url:'',
            container: 'msat-adwrap',
            init: function(){
                google_ad_client = "ca-pub-2152294856721899";
                /* 250x250 rich */
                google_ad_slot = "3929903770";
                google_ad_width = 250;
                google_ad_height = 250;
            },
            callback:function(){ console.log('msat-adwrap3'); }
        }).execute();
    </script>
    </body>
    </html>

复制代码 代码如下:

 

将script标签放到textarea标签中,等需要加载的时候再读取textarea的内容,这样可以实现真正的延迟加载script,这个方法要感谢玉伯提出的BigRender(墙外)方案。

    }

 if( fn ){
  loadQueue.unshift( 'runing' );
  fn();
 }
};

   // 恢复原生的document.write
   document.write = docWrite;
   head.removeChild( script );

2020欧洲杯冠军竞猜官方网站 2

实现了无阻塞式的延迟加载javascript广告代码,能否进一步优化?如果广告没在首屏出现,能否像通常的图片的延迟加载一样来进行延迟加载?答案是肯定的。对我之前写的图片延迟加载的小插件进行扩展,将原来的图片加载方式(替换src)改成上面的loadScript方式加载就可以实现。当然,仅仅是这样的修改还是会有问题的。如果有多个图片,并且loadScript是同时进行的,而document.write又是全局的方法,保不准在加载A的时候不影响到B,必须让它们一个个的按顺序加载,加载完A之后才能加载B。

2020欧洲杯冠军竞猜官方网站,document.write( "<a href=';"
"ad=6FF3F844_33E6_86EE_3B96_D94C1CF1AEC4;ap=2EBE5681_1BA3_4663_FA3F_E73D2B83FBDC;"

  • "pu=5173;/?' target='_blank'><img src='"
    "' "
    "border='0' width="132px" height="58px" /></a>" );

document.write是在页面渲染的时候同步进行的,必须要等javascript代码下载好并且document.write执行完后才接着渲染后面的内容,如果广告比较多的话,就会导致页面阻塞,尤其是在页面的首屏插好几个图片尺寸比较大的这种广告,那么阻塞情况就相当明显和严重,会让用户觉得你这个网页很慢。

复制代码 代码如下:

延迟加载script并重写document.write,下面是代码实现:

复制代码 代码如下:

上面比较关键的一步,延迟加载javascript代码,如何实现呢?先尝试通过改写script的type属性,比如将type设置成一个自定义的属性”type/cache”,但这样大部分浏览器(Chrome不会下载)仍然会下载这段代码,但不会执行,在页面渲染的时候下载这么一段代码仍然会阻塞,通过改写script的type并不能实现真正的延迟加载,最多能实现只加载不执行,而且还存在兼容问题。

很多第三方的广告系统都是使用document.write来加载广告,如下面的一个javascript的广告链接。

var loadQueue = [];
// 入列
var queue = function( data ){
 loadQueue.push( data );
 if( loadQueue[0] !== 'runing' ){
  dequeue();
 }
};
// 出列 
var dequeue = function(){
 var fn = loadQueue.shift();
 if( fn === 'runing' ){
  fn = loadQueue.shift();
 }

/**
 * 重写document.write实现无阻塞加载script
 * @param { Dom Object } textarea元素
 */
var loadScript = function( elem ){
 var url = elem.value.match( /src="([sS]*?)"/i )[1],
  parent = elem.parentNode,
  // 缓存原生的document.write
  docWrite = document.write, 
  // 创建一个新script来加载
  script = document.createElement( 'script' ),
  head = document.head ||
   document.getElementsByTagName( 'head' )[0] ||
   document.documentElement;

 // 重写document.write
 document.write = function( text ){
  parent.innerHTML = text;
 };

这种看似有点二的加载方式,但是你却没办法改造它,因为它本身就是第三方的。并且代码都添加了统计的功能,上面的javascript的广告链接每请求一次都会统计一次,生成的代码也有点击统计的功能,也就是说必须以这种方式来进行加载。

编辑:2020欧洲杯冠军竞猜官方网站 本文来源:write完结无阻塞加载js广告,write输出的广告无阻

关键词: 欧洲杯竞猜