javascript tutorial : utiliser les web worker partagés sharedworker html5




 

 
Je termine la série sur html5 et les web worker par ce qu’on appelle les web worker partagés ou SharedWorker. A l’opposé des web worker dédiés, les web worker partagés sont partageables par plusieurs pages HTML5 sans ajouter de complexité à l’utilisation. Un web worker partagé peut donc communiquer avec plusieurs pages à la fois. Je vous montre comment les utiliser.

 

Prérequis

– Savoir ce qu’est Javascript;
– en avoir fait un peu;
– un navigateur supportant les Web Workers (Google Chrome);
– de préférence un serveur apache fonctionnel sur lequel déployer les fichiers exemples;
– avoir lu les articles Multithreading Javascript avec les Web Worker HTML5, et Gestion des erreurs dans les web worker.

 

Quelle est la différence entre un Web Worker dédié et un Web Worker partagé en html5 ?

 

Web Worker html5 dédié

Imaginons 2 pages html5 distinctes hôtes instanciant chacune un objet Worker paramétrée avec un même script.

A l’affichage de ces 2 pages, pour chacune un processus / thread indépendant est crée pour chaque instanciation d’un objet Worker. Il y aura donc 2 processus : un pour chaque objet Worker instancié. Chaque Worker étant dédié à la page qui le lance, il ne peut communiquer qu’avec elle.

 

Web Worker html5 partagé

Imaginons 2 pages html5 distinctes hôtes utilisant chacune un objet SharedWorker paramétrée avec un même script.

A l’affichage de ces 2 pages, un seul processus / thread indépendant est créé : la première des 2 qui est affichée instancie le SharedWorker, la seconde le réutilise. Le SharedWorker peut communiquer avec les 2 pages simultanément.

 

Cinématique de l’exemple SharedWorker html5

L’exemple s’inspire de ceux des articles précédents sur les Web Worker : diffusion en temps réel de la date et l’heure.

L’exemple consiste à créer une page HTML5 munie d’un bouton qui déclenche la création d’une iframe dotée de 3 boutons :
– un bouton Démarrer qui crée, lance ou utilise un SharedWorker;
– un bouton Suspendre qui suspend le SharedWorker;
– et bouton Stopper qui stoppe le SharedWorker.

Le source de la page hôte des iframes : worker6.html

<html>
<head>
<title>DEMO WEB WORKER PARTAGE (SHAREDWORKER) HTML5 JAVASCRIPT</title>
</head>
<body>
<h1>DEMO 6 <strong><u>WEB WORKER HTML5 JAVASCRIPT</u></strong></h1>
<br>
- <strong>Démarrer Worker</strong> : Démarrer ou redémarre le Worker après qu'il ait été suspendu.
<br>
- <strong>Suspendre Worker</strong> : Mettre le Worker en pause, l'instance du Worker est toujours présente. Il peut être redémarré via le bouton <strong>Démarrer Worker</strong>.
<br>
- <strong>Stopper Worker</strong> : Stopper le Worker, l'instance du Worker est détruite. Il ne peut être redémarré via le bouton <strong>Démarrer Worker</strong>.
<br><br>
<input type="button" id="boutonNouvelleIFrame" value="Nouvelle IFrame pour SharedWorker">
<br><br>
</body>
<script>
var worker;
var numberOfDiv = 0;
var boutonNouveauWorker = document.getElementById("boutonNouvelleIFrame");
boutonNouveauWorker.onclick = function(e) {
  numberOfDiv++;
  var iframeTag = document.createElement("iframe");
  iframeTag.id = numberOfDiv;
  iframeTag.src = "innerHTMLIFrame.html";
  document.body.appendChild(iframeTag); 
};
</script>
</html>

Le source HTML de chaque iframe créé : innerHTMLIFrame.html

<body>
IFRAME <label id="numero"></label><br>
<label id="labelHeure">WORKER NON DEMARRE</label><br><br>
<input type="button" id="boutonDemarrerWorker" value="Démarrer">
<input type="button" id="boutonSuspendreWorker" value="Suspendre">
<input type="button" id="boutonStopperWorker" value="Stopper"><br>
</body>

La cinématique est la suivante :

– dans la page html5, on clique sur le bouton Nouvelle IFrame pour SharedWorker pour ajouter une iframe à la page;
– l’iframe apparaît dans la page et comporte les 3 boutons décrits précédemment;
– lorsqu’on clique sur le bouton Démarrer, l’iframe affiche l’heure en temps réel;
– lorsqu’on clique sur le bouton Suspendre, l’heure affichée s’arrête avec le message WORKER SUSPENDU;
– lorsqu’on clique sur le bouton Stopper, l’heure affichée s’arrête avec le message WORKER STOPPE.

On peut créer autant d’iframe que l’on souhaite. Dans ce cas et à partir de la 2ème iframe, chaque iframe nouvellement créée affiche d’emblée l’heure en temps réel.
Un clic sur le bouton Suspendre suspend l’affichage dans toutes les iframes créées.

 

Codage de l’exemple SharedWorker html5

La première iframe instancie un SharedWorker. Ce SharedWorker se met en écoute d’un événement : l’événement connect est intercepté lorsqu’un utilisateur créée ou se connecte au SharedWorker.

A partir de la deuxième iframe, aucune nouvelle instance de SharedWorker n’est créée, c’est l’instance créée avec la première iframe qui est réutilisée.

C’est par le biais de l’événement connect que le SharedWorker a connaissance d’un nouvel utilisateur.

A la connexion d’un nouvel utilisateur, le SharedWorker le sauvegarde dans un tableau (portList[ numberOfPort – 1 ] = port), l’abonne à l’événement message (port.onmessage) et démarre la connexion port.start().

Le source worker6.js

var intervalId;
var port;
var portList = new Array();
var numberOfPort = 0;

onconnect = function (event) {
  port = event.ports[0];
  numberOfPort++;
  portList[ numberOfPort - 1 ] = port;

  port.onmessage = function(e) {
   ......
  };

  port.start();
};

L’événement message auquel est abonné chaque utilisateur traite 3 cas correspondants aux 3 boutons Démarrer, Suspendre, et Stoppe :

– à la réception de la chaîne start, le SharedWorker exécute toutes les secondes la fonction envoyerDate chargée de diffuser l’heure à tous les utilisateurs/iframe connectés:

var envoyerDate = function() {
  for (var p=0; p<portList.length; p++)  {
    portList[ p ].postMessage( new Date() + '<br>Nb connexions = ' + numberOfPort );
  }
}

– à la réception de la chaîne pause, le SharedWorker stoppe l’exécution périodique de la fonction envoyerDate et exécute la fonction envoyerChaine qui diffuse à tous les utilisateurs/iframe l’heure et la chaîne de caractères « WORKER SUSPENDU »;

– à la réception de la chaîne stop, le SharedWorker stoppe l’exécution périodique de la fonction envoyerDate, exécute la fonction envoyerChaine qui diffuse à tous les utilisateurs/iframe l’heure et la chaîne de caractères « WORKER STOPPE », et stoppe l’exécution du Web Worker.

var envoyerChaine = function( chaine ) {
  for (var p=0; p<portList.length; p++)  {
    portList[ p ].postMessage( new Date() + " " + chaine + '<br>Nb connexions = ' + numberOfPort );
  }
}

Le fichier source worker6.js complet :

var intervalId;
var port;
var portList = new Array();
var numberOfPort = 0;

onconnect = function (event) {
  port = event.ports[0];
  numberOfPort++;
  portList[ numberOfPort - 1 ] = port;

  port.onmessage = function(e) {
    if ( e.data == "start" ) {
      intervalId = setInterval( envoyerDate, 1000);
    } else if ( e.data == "pause" ) {
      clearInterval( intervalId );
      envoyerChaine( "WORKER SUSPENDU" )
    } else if ( e.data == "stop" ) {
      clearInterval( intervalId );
      port.postMessage("WORKER STOPPE");
      port.close();
    }
  };
  port.start();
};

var envoyerDate = function() {
  for (var p=0; p<portList.length; p++)  {
    portList[ p ].postMessage( new Date() + '<br>Nb connexions = ' + numberOfPort );
  }
}

var envoyerChaine = function( chaine ) {
  for (var p=0; p<portList.length; p++)  {
    portList[ p ].postMessage( new Date() + " " + chaine + '<br>Nb connexions = ' + numberOfPort );
  }
}

Il ne reste plus qu’à instancier le SharedWorker html5 depuis chaque iframe et lancer la diffusion des messages sur clic des boutons Démarrer, Suspendre et Stopper.

Nous créons donc un fichier innerFrame.js à référencer dans le fichier innerHTMLIFrame.html comme suit :

<body>
IFRAME <label id="numero"></label><br>
<label id="labelHeure">WORKER NON DEMARRE</label><br><br>
<input type="button" id="boutonDemarrerWorker" value="Démarrer">
<input type="button" id="boutonSuspendreWorker" value="Suspendre">
<input type="button" id="boutonStopperWorker" value="Stopper"><br>
</body>
<script src="innerFrame.js"></script>

Le fichier innerFrame.js s’inspire fortement du source worker3.html de la démo 3 de l’article Multithreading Javascript avec les Web Worker html5

Le fichier source innerFrame.js

var worker;

if( !!window.Worker ) {
  // web workers supportes
  worker = new SharedWorker("./worker6.js");
  worker.port.addEventListener('message', function(e) {
    // mis a jour de l'affichage a reception du message du worker
    var label = document.getElementById("labelHeure");
      label.innerHTML = e.data;
    }, false);
  worker.port.start();
} else {
  // web workers non supportes
}

// clic sur boutons
var boutonDemarrerWorker = document.getElementById("boutonDemarrerWorker");
boutonDemarrerWorker.onclick = function(e) {
  worker.port.postMessage("start");
};
var boutonSuspendreWorker = document.getElementById("boutonSuspendreWorker");
boutonSuspendreWorker.onclick = function(e) {
  worker.port.postMessage("pause");
};

var boutonStopperWorker = document.getElementById("boutonStopperWorker");
boutonStopperWorker.onclick = function(e) {
  worker.port.postMessage("stop");
};

 
Pour voir l’exemple fonctionnel (préférez Chrome), cliquez ici.

 
[important]Nous avons fait le tour du sujet sur les Web Worker. Toutefois si mon propos ne vous paraissait pas clair, je vous invite à poser vos questions auxquelles je répondrais rapidement. Le cas échéant, cela me permettra d’améliorer cette série d’articles sur les Web Worker.[/important]

 

Posté dans html5Taggé javascript tutorial, tutorial web worker, tutorial web worker javascript, tutorial web workers, tutorial web workers partages, tutoriel shared web worker  |  Laisser un commentaire

Répondre

*