350 votes

Travailleurs Web sans fichier Javascript séparé?

Aussi loin que je peux dire, le web, les travailleurs doivent être écrites dans un autre fichier JavaScript, et appelé comme ceci:

new Worker('longrunning.js')

Je suis en utilisant le compilateur de fermeture à combiner et à rapetisser tout mon code source JavaScript, et je préfère ne pas avoir ma travailleurs dans des fichiers séparés pour la distribution. Est-il possible de faire cela?

new Worker(function() {
    //Long-running work here
});

Étant donné que la première classe des fonctions si importantes pour JavaScript, pourquoi la norme de façon à faire le travail de fond ont à charge un tout autre fichier JavaScript à partir du serveur?

281voto

vsync Points 11280

http://www.html5rocks.com/en/tutorials/workers/basics/#toc-inlineworkers

Si vous souhaitez créer votre travailleur script à la volée, ou de créer une page sans avoir à créer des fichiers d'opérateur? Avec une Goutte(), vous pouvez "inline" votre travailleur dans le même fichier HTML en tant que votre principale logique en créant une URL de la poignée pour le travailleur code de la chaîne


Exemple complet de BLOB inline travailleur:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
</head>
<body>

  <div id="log"></div>

  <script id="worker1" type="javascript/worker">
    // This script won't be parsed by JS engines because its type is javascript/worker.
    self.onmessage = function(e) {
      self.postMessage('msg from worker');
    };
    // Rest of your worker code goes here.
  </script>

  <script>
    function log(msg) {
      // Use a fragment: browser will only render/reflow once.
      var fragment = document.createDocumentFragment();
      fragment.appendChild(document.createTextNode(msg));
      fragment.appendChild(document.createElement('br'));

      document.querySelector("#log").appendChild(fragment);
    }

    var blob = new Blob([
      document.querySelector('#worker1').textContent
    ], { type: "text/javascript" })

    // Note: window.webkitURL.createObjectURL() in Chrome 10+.
    var worker = new Worker(window.URL.createObjectURL(blob));
    worker.onmessage = function(e) {
      log("Received: " + e.data);
    }
    worker.postMessage("hello"); // Start the worker.
  </script>
</body>
</html>

194voto

Adria Points 313

Le html5rocks solution de l'intégration de la web travailleur code HTML est assez horrible.
Et une goutte d'échappé JavaScript-comme-une-chaîne n'est pas mieux, pas moins, car il complique les flux de travail.

Personnellement, j'aime beaucoup le toString méthodes, mais @dan-l'homme QUI regex!

Mon approche préférée:

// Build a worker from an anonymous function body
var blobURL = URL.createObjectURL( new Blob([ '(',

function(){
    //Long-running work here
}.toString(),

')()' ], { type: 'application/javascript' } ) ),

worker = new Worker( blobURL );

// Won't be needing this anymore
URL.revokeObjectURL( blobURL );

Le soutien est l'intersection de ces trois tables:

37voto

Delan Azabani Points 33013

Vous pouvez créer un seul fichier JavaScript qui est conscient de son contexte d'exécution et peut agir à la fois comme un script parent et un travailleur. Commençons avec une structure de base d'un fichier comme ceci:

(function(global) {
    var is_worker = !this.document;
    var script_path = is_worker ? null : (function() {
        // append random number and time to ID
        var id = (Math.random()+''+(+new Date)).substring(2);
        document.write('<script id="wts' + id + '"></script>');
        return document.getElementById('wts' + id).
            previousSibling.src;
    })();
    function msg_parent(e) {
        // event handler for parent -> worker messages
    }
    function msg_worker(e) {
        // event handler for worker -> parent messages
    }
    function new_worker() {
        var w = new Worker(script_path);
        w.addEventListener('message', msg_worker, false);
        return w;
    }
    if (is_worker)
        global.addEventListener('message', msg_parent, false);

    // put the rest of your library here
    // to spawn a worker, use new_worker()
})(this);

Comme vous pouvez le voir, le script contient l'ensemble du code pour les parents et les travailleurs du point de vue de vérifier si son propre exemple, est un travailleur !document. Le un peu lourde script_path le calcul est utilisé pour calculer avec précision le chemin du script par rapport à la page parent, comme le chemin d'accès fourni à l' new Worker est par rapport à la page parent, pas le script.

29voto

dan-man Points 121

En utilisant la méthode Blob , que diriez-vous de cela pour une usine de travail:

 var BuildWorker = function(foo){
   var str = foo.toString()
             .match(/^\s*function\s*\(\s*\)\s*\{(([\s\S](?!\}$))*[\s\S])/)[1];
   return  new Worker(window.URL.createObjectURL(
                      new Blob([str],{type:'text/javascript'})));
}
 

Vous pourriez donc l'utiliser comme ça ...

 var myWorker = BuildWorker(function(){
   //first line of worker
   self.onmessage(){....};
   //last line of worker
});
 

MODIFIER:

Je viens d’étendre cette idée pour faciliter la communication entre threads: bridged-worker.js .

12voto

Sean Kinsey Points 17117

Web de travailleurs dans entièrement indépendantes des contextes individuels du Programme.

Cela signifie que le code ne peut pas être déplacé à partir d'un contexte à un autre en forme d'objet, comme ils seraient en mesure de faire référence à des objets par le biais des fermetures appartenant à l'autre contexte.
Ceci est particulièrement crucial que ECMAScript est conçu pour être un seul thread à la langue, et depuis web travaillent dans des threads séparés, vous serait alors le risque de non thread-safe les opérations effectuées.

Ce nouveau signifie que le web les travailleurs ont besoin d'être initialisé avec le code sous forme de code source.

La spécification de WHATWG dit

Si l'origine de la URL absolue n'est pas la même que la l'origine de l'entrée de script, puis jetez-la un SECURITY_ERR exception.

Ainsi, les scripts doivent être des fichiers externes avec le même schéma que l'original page: vous ne pouvez pas charger un script à partir d'un données: URL ou le javascript: URL, et une https: la page ne peut pas commencer à les travailleurs à l'aide de scripts avec http: Url.

mais, malheureusement, il n'a pas vraiment expliquer pourquoi on ne pouvait pas avoir permis de passer une chaîne de caractères code source pour le constructeur.

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