40 votes

Comment contourner les événements localStorage d'IE11 qui se déclenchent deux fois ou pas du tout dans les iframes ?

Je suppose que c'est un bogue, mais je n'ai pas pu trouver de discussion à ce sujet.

Il est connu qu'IE10 déclenchera (contre la spécification) les événements de stockage localement (c'est-à-dire dans le même contexte d'exécution global à partir duquel l'événement a été déclenché), mais IE11 semble s'éloigner encore plus de la spécification ( http://www.w3.org/TR/webstorage/ ) lorsqu'il s'agit d'iframes de même domaine :

  • si la iframe est intégrée à la page qui a déclenché l'événement de stockage, l'événement se déclenchera DEUX fois dans cette iframe.
  • si l'iframe est intégré à une page différente de celle qui a déclenché l'événement de stockage, l'événement ne se déclenchera pas du tout dans cet iframe.
  • si l'événement est déclenché à partir d'un iframe il se déclenchera DEUX fois localement et DEUX fois dans toute autre iframe intégrée à la même page, mais pas du tout dans les iframes d'autres pages.

Vous pouvez le tester en ouvrant le lien suivant dans deux onglets séparés : http://hansifer.com/main.html

Quelqu'un a-t-il une idée de cette bizarrerie ?

Dernière version testée : IE v11.0.9600.16476

Lien vers le rapport de bogue : https://connect.microsoft.com/IE/feedback/details/811546/ie11-localstorage-events-fire-twice-or-not-at-all-in-iframes

3voto

Schien Points 1224

Si vous voulez empêcher qu'un événement soit appelé plusieurs fois, quelle que soit la cause de l'invocation, utilisez un drapeau pour bloquer les événements suivants. Il existe plusieurs stratégies :

Supposons que vous ayez une fonction "func", et que vous souhaitiez qu'elle ne soit appelée qu'une seule fois dans les 200 ms :

function func(){
  if (document.func_lock) return;
  document.func_lock=true; // block future calls
  setTimeout(function(){document.func_lock=null;},300);
}

Lorsque plusieurs événements sont déclenchés en même temps, vous pouvez vous attendre à ce qu'ils arrivent tous dans la fenêtre de 300 ms. Le code ci-dessus peut être simplifié en tirant parti de la poignée du timer :

function func(){
  if (document.func_lock) return;
  document.func_lock=setTimeout(function(){return;},300);
}

Lorsque la minuterie expire, le verrou est automatiquement retiré.

.2. Retirer le drapeau en utilisant un callback. Le processus est trivial donc je ne posterai pas d'exemple de code ici.

En ce qui concerne le placement des drapeaux, vous pouvez utiliser n'importe quel objet DOM unique. Comme je ne connais pas le contexte de votre application, j'utiliserai simplement "document" ici. Vous pouvez également utiliser des clés de hachage qui sont particulières à votre application puisque vous avez déjà affaire à un stockage local. Le concept est le même.

2voto

Dalorzo Points 6449

J'ai pu contourner le problème en utilisant window.parent pour enregistrer l'événement dans l'iframe de cette manière :

Page Iframe

var win = window.parent || window.opener || window;
win.addEventListener('storage', handleLocalStorageEvent, false);

function handleLocalStorageEvent(e) {
    console.log('IFRAME local storage event', e);

    var sdf = document.getElementById('sdf');
    sdf.innerHTML = sdf.innerHTML + 'Storage Event => (' + e.newValue + ')<br>';
}

Avis de non-responsabilité : Veuillez noter que cette solution est destinée à résoudre le problème d'IE11. En aucun cas, il est prévu ou suggéré que cela s'applique à tous les navigateurs.

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