Un esempio di come è possibile, con le nuove feature di HTML 5 e JavaScript, gestire più thread in un processo separato tramite i Web Workers e farli comunicare con la pagina attraverso dei messaggi.
Allo stato attuale funziona su Internet Explore 10 e sulle ultime versioni di Firefox, Chrome, Opera e Safari

Demo

Nell'esempio propongo un contatore che si incrementa ogni 100 ms e può essere avviato, messo in pausa o fermato. Il conteggio è gestito in un thread separato contenuto nel file worker1.js. E' in un file separato perchè l'oggetto worker vuole un file .js separato dalla pagina che lo esegue. La comunicazione tra la pagina principale e il thread avviene tramite messaggi ed eventi (postMessage e onmessage).

HTML 5 Web Worker - Sgart.it

Result: 0

Codice

Per creare un Web Workers la procedura è questa:
  • si crea l'oggetto Worker passandogli il nome del file (new Worker(this.fileName))
  • si aggancia un evento per gestire i messaggi inviati dal thread (this.worker.onmessage)
  • nel codice JavaScript del worker si crea la funzione da eseguire (workerExecute) e si inviano i messaggi (postMessage(...))
  • se necessario, tramite setTimeout lo si esegue all'infinito
  • si gestisce l'evento onmessage per ricevere i messaggi inviati dalla pagina HTML Worker
Attenzione, alcuni browser, per impostazioni di sicurezza, bloccano l'esecuzione dei Worker se eseguiti da un percorso locale file://. Conviene sempre eseguirli tramite un webserver su protocollo http o https

HTML: default.html

<html>
<head>
  <title>HTML 5 Web Worker - Sgart.it</title>
</head>
<body>

<h1>HTML 5 Web Worker - Sgart.it</h1>
<div>
  Result: <span id="result">0</span>
  <div>
    <input type="button" value="start" onclick="sgart.worker.start()" />
    <input type="button" value="pause" onclick="sgart.worker.pause()" />
    <input type="button" value="stop" onclick="sgart.worker.stop()" />
  </div>
</div>


<script type="text/javascript">
var sgart =  sgart || {};
sgart.worker = {
  worker: null,
  fileName: "worker1.js",
  id: "result",
  start: function(){
    if(typeof(Worker) === "undefined") {
      document.getElementById(this.id).innerHTML = "Worker not supported - upgrade your browser";
    } else {
      var tmpID = this.id;
      // il worker deve essere in un file separato
      if(this.worker === null) {
        // creo l'oggetto Worker
        this.worker = new Worker(this.fileName);

        // gestisco l'evento per ricevere i messaggi dal worker
        this.worker.onmessage = function(ev){
          var msg = ev.data;
          document.getElementById(tmpID).innerHTML = msg.counter + " ( " + msg.name + " ) ";
        };
      } else {
        // invio i messaggi al Worker
        this.worker.postMessage("start");
      }
    }
  },
  pause: function(){
    if(this.worker !== null) {
      //invio un messaggio al worker
      this.worker.postMessage("pause");
    }
  },	
  stop: function(){
    if(this.worker !== null) {
      // termino e de-registro il worker
      this.worker.terminate();
      this.worker = null;
      document.getElementById(this.id).innerHTML = "stop";
    }
  }
}
</script>

</body>
</html>

JavaScript: worker1.js

// da questo file (il Worker) qui non posso accedere al DOM
var i = 0;
var pause = false;

// funzione da eseguire
function workerExecute()
{
  // costruisco l'oggetto da passare come messaggio 
  // ( posso usare anche valori semplici es: postMessage(i) )
  var msg = {counter: ++i, name: "workerExecute"};

  // invio il messaggio
  postMessage(msg);

  // rieseguo la funzione a cadenza regolare
  if (pause === true)
    pause = false;
  else
    setTimeout("workerExecute()", 100);
}

// gestisco l'evento che riceve i messaggi dalla pagina
onmessage = function (ev) {
  if (ev.data === "pause") {
    pause = true;
  } else if (ev.data === "start") {
    pause = false;
    workerExecute();
  }
  /*if (ev.data === "close") {
    var msg = {counter: 0, name: "close"};
    postMessage(msg);
    self.close();
  }*/ 
};

//eseguo il metodo quando viene istanziato
workerExecute(); 

Vedi anche W3C Web Workers
Tags:
HTML74 JavaScript184
Potrebbe interessarti anche: