359 Stimmen

Webworker ohne separate Javascript-Datei?

Soweit ich das beurteilen kann, müssen Web Worker in einer separaten JavaScript-Datei geschrieben und wie folgt aufgerufen werden:

new Worker('longrunning.js')

Ich verwende den Closure-Compiler, um meinen gesamten JavaScript-Quellcode zusammenzufassen und zu verkleinern, und ich möchte meine Worker nicht in separaten Dateien verteilen müssen. Gibt es eine Möglichkeit, dies zu tun?

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

Angesichts der Tatsache, dass erstklassige Funktionen für JavaScript so wichtig sind, stellt sich die Frage, warum die Standardmethode für die Arbeit im Hintergrund eine weitere JavaScript-Datei vom Webserver laden muss.

12voto

GG. Punkte 19294

Aktuelle Antwort (2018)

Sie können verwenden Greenlet :

Verschieben einer asynchronen Funktion in ihren eigenen Thread. Eine vereinfachte Einzelfunktionsversion von Workerize .

Beispiel:

import greenlet from 'greenlet'

const getName = greenlet(async username => {
  const url = `https://api.github.com/users/${username}`
  const res = await fetch(url)
  const profile = await res.json()
  return profile.name
})

console.log(await getName('developit'))

8voto

Chris Tobba Punkte 91

Eine besser zu lesende Möglichkeit für einen Inline-Arbeiter

    var worker_fn = function(e) 
    {
        self.postMessage('msg from worker');            
    };

    var blob = new Blob(["onmessage ="+worker_fn.toString()], { type: "text/javascript" });

    var worker = new Worker(window.URL.createObjectURL(blob));
    worker.onmessage = function(e) 
    {
       alert(e.data);
    };
    worker.postMessage("start");

7voto

trincot Punkte 257127

Eine einfache versprochene Version, Function#callAsWorker die ein thisArg und Argumente annimmt (genau wie call ), und gibt ein Versprechen zurück:

Function.prototype.callAsWorker = function (...args) {
    return new Promise( (resolve, reject) => {
        const code = `self.onmessage = e => self.postMessage((${this.toString()}).call(...e.data));`,
            blob = new Blob([code], { type: "text/javascript" }),
            worker = new Worker(window.URL.createObjectURL(blob));
        worker.onmessage = e => (resolve(e.data), worker.terminate());
        worker.onerror = e => (reject(e.message), worker.terminate());
        worker.postMessage(args);
    });
}

// Demo
function add(...nums) {
    return nums.reduce( (a,b) => a+b );
}
// Let the worker execute the above function, with the specified arguments
add.callAsWorker(null, 1, 2, 3).then(function (result) {
    console.log('result: ', result);
});

5voto

ubershmekel Punkte 10402

Ich nehme Adrias Antwort und füge sie in eine copy-pastable-Funktion ein, die mit dem aktuellen Chrome und FF funktioniert, aber nicht mit IE10 (worker from blob verursacht ein Sicherheitsfehler ).

var newWorker = function (funcObj) {
    // Build a worker from an anonymous function body
    var blobURL = URL.createObjectURL(new Blob(
        ['(', funcObj.toString(), ')()'],
        {type: 'application/javascript'}
     ));

    var worker = new Worker(blobURL);

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

    return worker;
}

Und hier ist ein funktionierendes Beispiel http://jsfiddle.net/ubershmekel/YYzvr/

4voto

Chad Scira Punkte 9375

Je nach Anwendungsfall können Sie etwas verwenden wie

aufgabe.js Vereinfachte Schnittstelle, um CPU-intensiven Code auf allen Kernen laufen zu lassen (node.js und Web)

Ein Beispiel wäre

function blocking (exampleArgument) {
    // block thread
}

// turn blocking pure function into a worker task
const blockingAsync = task.wrap(blocking);

// run task on a autoscaling worker pool
blockingAsync('exampleArgumentValue').then(result => {
    // do something with result
});

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X