środa, 31 października 2012

[HTML|JS|CSS] HTML5: Web Workers

Web Workers to funkcjonalność, która umożliwia wykonywanie długotrwałych operacji w tle. Główną korzyścią jest więc responsywny interfejs użytkownika podczas wykonywania tych operacji. Kilka wad, jakie pojawiają się przy korzystaniu z WW, to przede wszystkim ograniczenia, a pośród nich brak dostępu do:
  • DOM
  • Window
  • Host page
Kolejnym problemem może być fakt, że kod wykonywany przez workera powinien być pisany tylko w JavaScripcie. W związku z tym nie możemy korzystać z popularnych bibliotek jak na przykład jQuery.  Pomimo tych problemów, wciąż mamy dostęp do takich mechanizmów, jak:
  • navigator
  • timeout
  • XHR
Aby skorzystać z Web Workera musimy użyć funkcji konstruktora Worker, komunikacja odbywa się poprzez funkcję postMessage, gdzie dane przekazuje się jako argumenty. Aby przerwać działanie wystarczy wywołać funkcję terminate().

Poniżej przykład obliczania w tle silni dla zadanej ilości liczb.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Web workers</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript" src="script.js"></script>
</head>
<body>
 <h3>Factorial calculator</h3>
 <div>
  <span>
   <input type="number" id="count" />
   <button id="start">Start</button>
   <button id="terminate">Terminate</button>
  </span>
 </div>
 <div>
  <ol id="list">
  </ol>
 </div>
</body>
</html>

Plik ze skryptem:

var worker;

$(function(){
 $('#start').click(function(){
  $('#list').html("");
  var count = $('#count').val();
  var settings = {};
  settings.count = parseInt(count);
  worker = new Worker('factorial.js');
  worker.onmessage = function(event){
   var list = event.data;
   $.each(list, function(){
    printNumber(this);
   })
  };
  worker.postMessage(settings);
 });

 $('#terminate').click(function(){
  if(worker){
   worker.terminate();
  }
 });
});

function printNumber(number){
 $('#list').append('<li>'+number+'</li>');
}

Plik factorial.js

var results = [];

function messageHandler(e){
 if(e.data.count > 0){
  calculatefactorial(e.data.count);
 }
}

function factorial(n){
 if(n < 2){
  return 1;
 }
 else
  return n*factorial(n-1);
}

function calculatefactorial(length){
 for(var i = 1; i <= length; i++){
   results.push(factorial(i));
  }; 
 setTimeout(function(){
  postMessage(results);
 }, i*100);
 
}

addEventListener("message", messageHandler, true);

Brak komentarzy:

Prześlij komentarz