71 votes

La définition d’une URL de données sur URL de données doit-elle être disponible immédiatement?

Considérez les points suivants (fragile) du code JavaScript:

var img = new Image;
img.src = "data:image/png;base64,..."; // Assume valid data

// Danger(?) Attempting to use image immediately after setting src
console.log( img.width, img.height );
someCanvasContext.drawImage( img, 0, 0 );

// Danger(?) Setting onload after setting src
img.onload = function(){ console.log('I ran!'); };

La Question(s)

  • Si la largeur de l'image et de la hauteur correcte immédiatement?
  • Si la toile dessiner le travail tout de suite?
  • Si l' onload callback (mise après la src a été modifié), - elle être invoquée?

Les Tests Expérimentaux
J'ai créé une simple page de test avec le même code. Dans Safari de mes premiers essais, à la fois par l'ouverture de la page HTML en local (file:/// url) et de le charger à partir de mon serveur, ont montré ce travail: la hauteur et la largeur est correct, la toile dessiner des œuvres, et l' onload aussi des incendies.

Dans Firefox v3.6 (OS X), le chargement de la page après avoir lancé le navigateur montre que la hauteur/largeur est pas correcte immédiatement après le réglage, drawImage() d'échec. ( onload Gestionnaire n'feu, cependant.) Le chargement de la page à nouveau, cependant, montre que la largeur/hauteur correcte immédiatement après le réglage, et drawImage() de travail. Il semblerait que Firefox met en cache le contenu des données de l'URL d'une image et l'a immédiatement disponible lorsque utilisé dans la même session.

Dans Chrome v8 (OS X) je vois les mêmes résultats que dans Firefox: l'image n'est pas disponible immédiatement, mais prend un certain temps, de manière asynchrone "charge" à partir des données de l'URL.

En plus de la preuve expérimentale de ce que les navigateurs ci-dessus fait ou ne fonctionne pas, j'aimerais vraiment des liens vers les specs sur la façon dont cela est censé se comporter. Jusqu'à présent, mon Google-fu n'a pas été à la hauteur de la tâche.

Jouer En Toute Sécurité
Pour ceux qui ne comprennent pas pourquoi le ci-dessus peut être dangereux, sachez que vous devez utiliser les images comme ça pour être sûr:

// First create/find the image
var img = new Image;

// Then, set the onload handler
img.onload = function(){
  // Use the for-sure-loaded img here
};

// THEN, set the src
img.src = '...';

52voto

Phrogz Points 112337

Comme personne n'a encore trouvé aucune précision sur la façon dont cela est censé se comporter, nous devons être satisfaits de la façon dont elle ne se comportent. Voici les résultats de mes tests.

 | données d'image utilisable à droite | à ne onload rappel après la src
 | après le réglage de la src? | est changé encore appelé?
------------+-----------------------------+-------------------------------------
Safari 5 | oui | oui 
------------+-----------------------------+-------------------------------------
Chrome 8 | **n* * * (1er chargement de la page), mais | oui 
FireFox 3.6 | oui par la suite (en cache) | 
------------+-----------------------------+-------------------------------------
IE8 | oui (32 ko de données limite) | oui 
------------+-----------------------------+-------------------------------------
IE9b | oui | **non** * 
------------+-----------------------------+-------------------------------------

En résumé:

  • Vous ne pouvez pas supposer que les données de l'image sera disponible juste après la définition d'une data-uri; vous devez attendre pour l' onload événement.
  • En raison de IE9, vous ne pouvez pas définir l' onload gestionnaire d'après la définition de l' src et s'attendre à être appelé.
  • Les recommandations de "Jouer la Sécurité" (à partir de la question ci-dessus) sont la seule façon de garantir le bon comportement.

Si quelqu'un peut trouver les specs de discuter de cela, je serai heureux d'accepter leur réponse à la place.

6voto

Marcel Korpel Points 14633

Après avoir donné le contrôle de retour pour le navigateur du moteur de rendu, les rapports de test true dans FF 4b9 et Chrome 8.0.552.237. J'ai modifié ces pièces:

img.onload = function(){   // put this above img.src = …
    document.getElementById('onload').innerHTML = 'yes';
};
img.src = img_src;
…
window.setTimeout(function () {   // put this inside setTimeout
    document.getElementById('wh').innerHTML = (img.height==img.width) && (img.height==128);
}, 0);

Mise à jour: Oui, je comprends cette "réponse" est plus comme un commentaire, mais je voulais juste le signaler. Et après le test j'obtiens des résultats reproductibles:

  • sans setTimeout, dans les deux navigateurs-je obtenir de l' false la première fois que j'ai ouvert la page et true seulement après l'appui sur la touche F5. Après explicitement vider le cache à la fois dire false nouveau après le rechargement.
  • avec setTimeout la largeur/hauteur de test toujours evualuates d' true.

Dans les deux cas, l'image n'est pas la première fois, qu'après le rechargement de la page.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X