2017-01-23 1 views
0

Fondamentalement, j'ai ces deux lignes de code écrites juste après l'autre .:Comment trouver le contexte dans lequel document.write fonctionne. Pouvez-vous résoudre l'énigme

console.log(typeof (noAdsCallback)); 
document.write('<sc' + 'ript type="text/javascript">console.log(typeof(noAdsCallback));</scr' + 'ipt>'); 

Le premier enregistre function, les deuxièmes journaux undefined.

Bien sûr, c'est un peu plus compliqué que ça. Donc, voici la mise en place en un mot:

J'ai une soi-disant cascade de fournisseurs d'annonces. Cela signifie que j'essaie de charger des annonces en écrivant (en utilisant document.write) des tags spéciaux (donnés par mon fournisseur d'annonces).

Si le fournisseur ne trouve pas une annonce pour moi, qu'ils envoient un javascript qui-extrait ressemble à ceci:

if (typeof(window.noAdsCallback) === "function") noAdsCallback(); 

Cette fonction essentiellement les balises écrit du fournisseur suivant, qui fait la même comme le premier jusqu'à ce que j'atteigne la fin de la liste.

Ce système fonctionne réellement bien, faisant exactement ce que je veux qu'il fasse. Les deux lignes données au début du journal function. Sauf si j'utilise Google en tant que fournisseur de publicités. Il y a une chose que Google fait différemment, qui semble tout gâcher.

Dans Google, je ne peux pas définir un extrait JavaScript de secours. Tout ce que je peux faire est de fournir une URL de secours. Donc cet fallback-url (puisqu'il est chargé dans un iframe à l'intérieur d'un iframe à l'intérieur ...) envoie un postMessage au début, qui appelle alors la même méthode noAdsCallback(). Et cela aussi fonctionne très bien. Le message est reçu et la bonne méthode est exécutée. Cependant, déjà les deux lignes donnent déjà des résultats différents, à savoir function et undefined respectivement

Le fournisseur suivant ne parvient pas à trouver le noAdsCallback() Méthode, quand il retourne, car il utilise document.write pour essayer de l'exécuter. D'une certaine manière, le contexte a été perdu.

Premier indice: Cela fonctionne très bien (c'est-à-dire les deux lignes log function) dans Chrome, mais cela ne fonctionne pas dans FF ou IE.

Deuxième indice: Cela fonctionne bien, tant que le contexte ne change jamais, mais si la communication s'exécute à tout moment via la messagerie, elle devient confuse. L'utilisation de la fantastique bibliothèque postscribe mentionnée ci-dessous résout en fait le problème, mais en introduit de nouveaux à un autre endroit.

Quatrième indice: Le débogage de window.name, avant d'utiliser document.write, donne le nom correct, donc je ne suis pas dans un iFrame aléatoire.

Pensées de finition. Je sais, je sais: N'UTILISEZ PAS DE DOCUMENT ECRIRE !! Je le sais. Mais depuis Adproviders utilisent tout le temps, je suis obligé de l'utiliser pour, sinon je reçois ceci:

Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened. 

En fait, en ce moment j'utilise postscribe (https://github.com/krux/postscribe) et il fonctionne comme un charme, à l'exception pour un fournisseur de poux. Et la solution de workauround serait, d'utiliser un document.écrivez seulement pour ce fournisseur moche et postscribe pour tous les autres. Mais j'aimerais vraiment savoir quelle est la racine du problème.

Toutes les idées, très appréciées.

Répondre

1

Je pense que je l'ai compris maintenant. Longue histoire courte: N'UTILISEZ PAS DOCUMENT.WRITE :)

Essayez de vous inscrire, si vous devez. Donc, en rétrospective, c'est évident, parce qu'en fait, partout où vous lisez sur document.write(), write() efface tout le document. Et je ne l'ai pas compris, parce que je ne l'ai jamais vu et que toutes les publicités l'utilisent, comme tout le temps. De plus, il semblait fonctionner correctement sur Chrome. Alors que se passe-t-il??

Eh bien, voici ce qui se passe. Tant que le document est ouvert, ce qui signifie essentiellement qu'il est en cours d'écriture, document.write() ne fait qu'ajouter au flux et n'efface pas le document. Et tant que j'utilise document.write(), pour ajouter des scripts publicitaires étrangers (qui peuvent contenir et contiendront document.write()), la page ne se ferme pas, donc le document reste ouvert.

C'est la raison pour laquelle l'ajout de Google à ma cascade a posé un problème: Google met tout dans les iframes. Ainsi, la page contenant le modèle cascade ne voit que l'iframe et dit: "en ce qui me concerne, j'ai terminé" et ferme le document, alors que Google est toujours là. Par la suite, Google n'a pas trouvé d'annonce et envoie un postMessage à la page principale, provoquant l'utilisation du fournisseur suivant. Qui utilise ensuite document.write() et efface tout.

Tout? Pas tout. Rappelez-vous, il a toujours l'habitude de travailler quand j'ai utilisé Chrome? La raison en est que Chrome efface juste le HTML mais laisse le Javascript intact. Donc, sur Chrome, mon Javascript-cascade a bien fonctionné, car tous les objets JS étaient toujours en place. Tous les autres navigateurs l'ont effacé.

Alors c'est tout. Probablement personne ne le lira, mais si vous le faites, utilisez POSTSCRIBE! Maintenant que j'ai enfin vraiment compris document.write() et document.open() et document.close() je suis un grand fan.