Le chargement non bloquant de javascript joue un grand rôle dans l'optimisation des performances de la page. Cela peut réduire efficacement le blocage de js lors du chargement de la page. Surtout pour certains fichiers publicitaires js, puisque le contenu publicitaire peut être riche en médias, cela peut devenir un goulot d'étranglement pour la vitesse de chargement de votre page. Javascript haute performance nous dit, étudiants, d'augmenter la vitesse de votre page Web, de charger JS sans bloquer.
Ensuite, le code suivant apparaît.
(function() { var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'http://yourdomain.com/script.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); })();
Tout le monde connaît ce qui précède. Les étudiants qui ont lu le livre connaissent tous les avantages du chargement non bloquant. Lorsque de tels scripts non bloquants rencontrent des publicités js ordinaires, des problèmes d'écriture surviennent - le code publicitaire. apparaît dans le code HTML mais aucune annonce n'est affichée.
Nani ? Le code HTML n'est pas affiché sur la page après sa sortie ?
Regardez d'abord le code js publicitaire
Le code est assez simple, juste un document.write produisant du code HTML (je crois que les annonces de nombreux annonceurs sont comme ça). Quel est le problème avec la page qui n'affiche pas d'annonces ? Le problème réside dans ce document.write. Pourquoi? Jetons d'abord un coup d'œil à w3schools pour voir en quoi la définition de document.write est très utile.
Définition et usage
La méthode write() écrit des expressions HTML ou du code JavaScript dans le document.
Plusieurs paramètres (exp1, exp2, exp3,...) peuvent être répertoriés et ils seront ajoutés au document dans l'ordre.
Méthode :
L'une consiste à utiliser cette méthode pour afficher du HTML dans le document, et l'autre consiste à générer un nouveau document dans une fenêtre ou un cadre autre que la fenêtre dans laquelle cette méthode est appelée. Dans le second cas, veillez à utiliser la méthode close() pour fermer le document.
Mais le principe est qu'il est exécuté pendant le processus de saisie du flux de page. Une fois la page chargée, appeler à nouveau document.write() appellera implicitement document.open() pour effacer le document actuel et démarrer un nouveau document. C'est-à-dire que si nous utilisons à nouveau document.write après le chargement du HTML, le HTML généré précédemment sera supprimé et le contenu généré par document.write sera affiché.
Dans notre exemple, si document.write est affiché en HTML après le chargement de la page, il ne sera pas exécuté. Maintenant que nous connaissons le problème et le principe, comment résoudre ce problème ?
En utilisant ajax de manière asynchrone, les lignes sont différentes. De nombreux fichiers publicitaires sont tiers Sous différents noms de domaine, il existe des problèmes entre domaines et nous ne pouvons pas contrôler la sortie de leurs codes. Dans ce cas, nous avons pensé à un moyen de réécrire document.write, puis de réécrire document.write une fois le fichier js chargé. Regardez le code.
La première version charge les publicités js sans bloquer :
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(); } };
Code d'appel de la page :
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();
Code js publicitaire
//ad.js document.write('<img src="http://images.cnblogs.com/logo_small.gif" alt="Logo">'); //ad2.js document.write('<img src="http://www.baidu.com/img/baidu_sylogo1.gif" width="270" height="129" usemap="#mp">'); //ad3.js document.write('<img alt="Google" height="95" id="hplogo" src="http://www.google.com/images/srpr/logo3w.png" width="275">');
Le problème avec la première version est que lorsque plusieurs fichiers sont appelés, certains problèmes surviendront :
1. En raison des différentes vitesses de chargement des fichiers, certains peuvent être chargés en premier et d'autres peuvent être chargés plus tard, ce qui est désordonné, et souvent ce dont nous avons besoin est ordonné. Par exemple, nous devons d’abord charger la publicité sur le premier écran.
2. Je pense que certaines annonces doivent définir certains paramètres à l'avance, comme Google Adsense
Afin de résoudre ces deux problèmes, nous l'avons encore modifié dans la version finale js à chargement non bloquant.
Code de la page 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:'http://pagead2.googlesyndication.com/pagead/show_ads.js', 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>
code source de loadscript.js
/** * 无阻塞加载广告 * @author Arain.Yu */ var loadScript = ( function() { var adQueue = [], dw = document.write; //缓存js自身的document.write function LoadADScript(url, container, init, callback) { this.url = url; this.containerObj = ( typeof container == 'string' ? document.getElementById(container) : container); this.init = init || function() { }; this.callback = callback || function() { }; } LoadADScript.prototype = { startLoad : function() { var script = document.createElement('script'), _this = this; _this.init.apply(); 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; } 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(); } } }; return { add : function(adObj) { if(!adObj) return; adQueue.push(new LoadADScript(adObj.url, adObj.container, adObj.init, adObj.callback)); return this; }, execute : function() { if(adQueue.length > 0) { adQueue[0].startLoad(); } } }; }());