Ayrı bir Javascript dosyası olmayan Web çalışanları?


292

Anlayabildiğim kadarıyla, web çalışanlarının ayrı bir JavaScript dosyasına yazılması ve şu şekilde adlandırılması gerekir:

new Worker('longrunning.js')

Tüm JavaScript kaynak kodumu birleştirmek ve küçültmek için kapatma derleyicisini kullanıyorum ve dağıtım için çalışanlarımın ayrı dosyalarda olmasını istemem. Bunu yapmanın bir yolu var mı?

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

Birinci sınıf işlevlerin JavaScript için çok önemli olduğu düşünüldüğünde, arka plan çalışması için standart yolun neden web sunucusundan başka bir JavaScript dosyası yüklemesi gerekir?


7
Çünkü yürütme bağlamını tamamen güvenli bir şekilde saklamak birinci sınıf işlevlerden daha da önemlidir :-)
Pointy

1
Üzerinde çalışıyorum (ya da sorunu en aza indirgemek): DynWorker . Şunları yapabilirsiniz: var worker = new DynWorker(); worker.inject("foo", function(){...});...
Félix Saparelli


1
OP, "JavaScript kaynak dosyası yerine işlevi kabul etmeyi öğreten İşçi" sorusunu sildi. Cevap burada
Rob W

Bunu daha kolay hale getirmek için task.js'yi geliştirdim . Çoğu zaman sadece küçük kilitleme görevlerini boşaltmaya çalışıyorsunuz.
Chad Scira

Yanıtlar:


225

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

Çalışan betiğinizi anında oluşturmak veya ayrı çalışan dosyaları oluşturmak zorunda kalmadan bağımsız bir sayfa oluşturmak isterseniz ne olur? Blob () ile, işçi koduna dize olarak bir URL tanıtıcısı oluşturarak, işçinizi ana mantığınızla aynı HTML dosyasında "satır içi" yapabilirsiniz


BLOB satır içi çalışanının tam örneği:

<!DOCTYPE html>
<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>
  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) {
    console.log("Received: " + e.data);
  }
  worker.postMessage("hello"); // Start the worker.
</script>


Yalnızca Google Chrome çözümü, Firefox 10'un destekleyeceği anlaşılıyor, diğer tarayıcılar hakkında bilmiyorum
4esn0k

2
BlobBuiler artık kullanımdan kaldırıldı . Kullanım Blob yerine. Şu anda en yeni Firefox / WebKit / Opera ve IE10'da desteklenmektedir, eski tarayıcılar için uyumluluk tablolarına bakın .
Félix Saparelli

3
Blob yapıcısı IE10'da desteklenebilir, ancak javascript'i web çalışanına (IE11'de bile değil) geçiremezsiniz: connect.microsoft.com/IE/feedback/details/801810/… .
jayarjo

1
@albanx -Ne testleri? internette zaten diş açmanın milyarlarca tarayıcıyı kapatmadığını gösteren milyar demo sayfası var.
vsync

2
@albanx - en azından hangi hangisinin hangi hangisini kullandığınızı hangi hangilerinin hang hang hang hang hang hang hang hang hang asersın hangisinde kullandığınızı hangileri? bu demo sizin için hangisi? ie.microsoft.com/testdrive/Graphics/WorkerFountains/…
vsync

162

HTML'de web çalışanı kodunu gömmenin html5rocks çözümü oldukça korkunç.
Ve dize olarak kaçan JavaScript bloğu daha iyi değildir, en azından iş akışını karmaşıklaştırdığı için değil (Kapatma derleyicisi dizelerde çalışamaz).

Şahsen ben toString yöntemlerini seviyorum, ama @ dan-man BU regex!

Tercih ettiğim yaklaşım:

// 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 );

Destek, bu üç tablonun kesişimidir:

Ancak bu, SharedWorker için işe yaramaz , çünkü isteğe bağlı 'name' parametresi eşleşse bile URL'nin tam eşleşme olması gerekir. SharedWorker için ayrı bir JavaScript dosyasına ihtiyacınız olacaktır.


2015 güncellemesi - ServiceWorker tekilliği geldi

Şimdi bu sorunu çözmenin daha güçlü bir yolu var. Yine, çalışan kodunu bir işlev olarak (statik bir dize yerine) depolayın ve .toString () kullanarak dönüştürün, ardından kodu, seçtiğiniz statik bir URL altında CacheStorage'a ekleyin.

// Post code from window to ServiceWorker...
navigator.serviceWorker.controller.postMessage(
 [ '/my_workers/worker1.js', '(' + workerFunction1.toString() + ')()' ]
);

// Insert via ServiceWorker.onmessage. Or directly once window.caches is exposed
caches.open( 'myCache' ).then( function( cache )
{
 cache.put( '/my_workers/worker1.js',
  new Response( workerScript, { headers: {'content-type':'application/javascript'}})
 );
});

İki olası geri dönüş vardır. Yukarıdaki gibi ObjectURL veya daha sorunsuz bir şekilde /my_workers/worker1.js dosyasına gerçek bir JavaScript dosyası koyun

Bu yaklaşımın avantajları:

  1. Paylaşılan Çalışanlar da desteklenebilir.
  2. Sekmeler, önbelleğe alınmış tek bir kopyayı sabit bir adreste paylaşabilir. Blob yaklaşımı, her sekme için rastgele objectURL'leri çoğaltır.

4
Tarayıcı uyumluluğu bu çözümde nasıl görünür?
Ben Dilts

Bu çözümü ayrıntılı olarak açıklayabilir misiniz, nasıl çalışır? Worker1.js dosyası nedir? Ayrı bir js dosyası mı? Bunu kullanmaya çalışıyorum ama çalışmasını sağlayamıyorum. Özellikle bir SharedWorker için çalışmak için çalışıyorum
Yehuda

Keşke yararlı bir fonksiyonda tamamlayabilirsiniz!
mmm

@ Ben Dilts: Tarayıcı uyumluluğu, kodunuzu babel üzerinden çalıştırmak gibi görünecektir: babeljs.io/repl
Jack Giffin

Standart, Function.prototype.toString () işlevinin işlev gövdesini dize olarak döndürdüğünü garanti etmez. Muhtemelen cevaba bir uyarı eklemelisiniz.
RD

37

Yürütme içeriğinin farkında olan ve hem üst komut dosyası hem de çalışan olarak işlev görebilen tek bir JavaScript dosyası oluşturabilirsiniz. Bunun gibi bir dosya için temel bir yapı ile başlayalım:

(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);

Gördüğünüz gibi, komut dosyası hem ebeveynin hem de işçinin bakış açısının tüm kodunu içerir ve kendi bireysel örneğinin bir çalışan olup olmadığını kontrol eder !document. Biraz gereksiz script_pathhesaplama, verilen yol komut dosyasına değil, üst sayfaya göreli olduğundan, komut dosyasının yolunu üst sayfaya göre doğru bir şekilde hesaplamak için kullanılır new Worker.


4
Siteniz kayboldu; yeni bir URL'niz var mı?
BrianFreud

1
Bu ilginç bir yaklaşım. FWIW, "self" (Web Worker global nesnesi) ve "window" varlığını kontrol ederek Web Workers'ı tespit ediyorum.
pwnall

PapaParse'ın Web Çalışanlarını nasıl ele aldığını araştırdım ve bu yaklaşımı benimsiyorlar github.com/mholt/PapaParse
JP DeVries

Bence 'typeof importScripts! == null' kullanarak test script çalışan kapsamında çalıştığını söyleyebilir.
MeTTeO

1
Önceki öğenin script öğesinden ne olduğunu anlamıyorum. Birisi bana açıklayabilir mi?
Teemoh

28

BlobYöntemi kullanarak, bir işçi fabrikası için buna ne dersiniz:

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'})));
}

Yani bu şekilde kullanabilirsiniz ...

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

DÜZENLE:

İş parçacıkları arası iletişimi kolaylaştırmak için bu fikri biraz daha genişlettim: bridged-worker.js .

DÜZENLEME 2:

Yukarıdaki bağlantı, oluşturduğum bir öz ile ilgilidir. Başka biri daha sonra gerçek bir repoya dönüştürdü .


11

Web çalışanları tek tek Programlar olarak tamamen ayrı bağlamlarda çalışırlar.

Bu, kodun başka bir nesneye ait kapaklar aracılığıyla nesnelere başvurabileceği için nesne biçiminde bir bağlamdan diğerine taşınamayacağı anlamına gelir.
ECMAScript tek iş parçacıklı bir dil olarak tasarlandığından bu özellikle önemlidir ve web çalışanları ayrı iş parçacıklarında çalıştığından, iş parçacığı için güvenli olmayan işlemlerin gerçekleştirilme riskiniz olur.

Bu yine web çalışanlarının kaynak formunda kodla başlatılması gerektiği anlamına gelir.

WHATWG'den gelen spec diyor

Sonuçta elde edilen mutlak URL'nin kaynağı giriş komut dosyasının kaynağıyla aynı değilse, SECURITY_ERR istisnası atın.

Bu nedenle, komut dosyaları orijinal sayfa ile aynı şemaya sahip harici dosyalar olmalıdır: bir veri: URL veya javascript: URL'den komut dosyası yükleyemezsiniz ve bir https: sayfası, http: URL'leri olan komut dosyalarını kullanan çalışanları başlatamaz.

ancak ne yazık ki, neden yapıcıya kaynak kodlu bir dize geçirilmesine izin verilemediğini açıklamıyor.


6

bir satır içi çalışan için daha iyi bir okuma yolu ..

    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"); 

Yaptığım şey, tüm işçi koduyla bir işlev oluşturmak, bu işlevi geçmek toString(), vücudu uzatmak ve daha sonra bunu bir Blob'a koymaktı. Son cevaba bakın, bir
Fernando Carvajal

5

Adria'nın yanıtını almak ve geçerli Chrome ve FF ile çalışan ancak IE10 ile çalışmayan kopyalanabilir bir işleve koymak (blob çalışanı bir güvenlik hatasına neden olur ).

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;
}

Ve işte çalışan bir örnek http://jsfiddle.net/ubershmekel/YYzvr/


5

Son cevap (2018)

Greenlet'i kullanabilirsiniz :

Eşzamansız bir işlevi kendi iş parçacığına taşıyın. Çalışanlaştırmanın basitleştirilmiş tek işlevli bir sürümü .

Misal:

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'))

3

Kullanım durumunuza bağlı olarak,

task.js Tüm çekirdeklerde (node.js ve web) CPU yoğun kod çalıştırmak için basitleştirilmiş arayüz

Bir örnek

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
});

2

VkThread eklentisine bir göz atın. Htis eklentisi ile ana kodunuzdaki herhangi bir işlevi alıp bir iş parçacığında (web çalışanı) çalıştırabilirsiniz. Bu nedenle, özel bir "web çalışanı dosyası" oluşturmanız gerekmez.

http://www.eslinstructor.net/vkthread/

--Vadim


1

Satır içi web çalışanlarını kullanarak aynı javascript dosyasındaki web çalışanlarını kullanabilirsiniz.

Aşağıdaki makale, web işçilerini ve web işçilerinin sınırlamalarını ve hata ayıklamalarını kolayca anlamanıza yönelik olacaktır.

Web çalışanlarında ustalaşma


1

Bunu yapmanın en iyi yolunun bir Blob nesnesi kullanmak olduğunu düşünüyorum, aşağıda basit bir örnek görebilirsiniz.

// create a Blob object with a worker code
var blob = new Blob(["onmessage = function(e) { postMessage('msg from worker'); }"]);

// Obtain a blob URL reference to our worker 'file'.
var blobURL = window.URL.createObjectURL(blob);

// create a Worker
var worker = new Worker(blobURL);
worker.onmessage = function(e) {
  console.log(e.data);
};
worker.postMessage("Send some Data"); 


1

burada konsol:

var worker=new Worker(window.URL.createObjectURL(new Blob([function(){
  //Long-running work here
  postMessage('done');
}.toString().split('\n').slice(1,-1).join('\n')],{type:'text/javascript'})));

worker.addEventListener('message',function(event){
  console.log(event.data);
});

1

https://developer.mozilla.org/es/docs/Web/Guide/Performance/Using_web_workers

    // Syntax: asyncEval(code[, listener])

var asyncEval = (function () {

  var aListeners = [], oParser = new Worker("data:text/javascript;charset=US-ASCII,onmessage%20%3D%20function%20%28oEvent%29%20%7B%0A%09postMessage%28%7B%0A%09%09%22id%22%3A%20oEvent.data.id%2C%0A%09%09%22evaluated%22%3A%20eval%28oEvent.data.code%29%0A%09%7D%29%3B%0A%7D");

  oParser.onmessage = function (oEvent) {
    if (aListeners[oEvent.data.id]) { aListeners[oEvent.data.id](oEvent.data.evaluated); }
    delete aListeners[oEvent.data.id];
  };


  return function (sCode, fListener) {
    aListeners.push(fListener || null);
    oParser.postMessage({
      "id": aListeners.length - 1,
      "code": sCode
    });
  };

})();


1

Bu yüzden şimdi ES6'daki şablon değişmezleri sayesinde bunun için harika bir seçeneğimiz var. Bu, ekstra çalışan işlevinden (ve garip kapsamından) vazgeçmemize ve yalnızca metin depolamak için kullandığımız gibi, aslında bir belgeye veya DOM'ye ihtiyaç duymadan, işçiye yönelik kodu çok satırlı metin olarak yazmamızı sağlar. bunu yapmak için. Örnek:

const workerScript = `
self.addEventListener('message', function(e) {
  var data = e.data;
  console.log('worker recieved: ',data);
  self.postMessage('worker added! :'+ addOne(data.value));
  self.close();//kills the worker
}, false);
`;

İşte bu yaklaşımın geri kalanının bir özeti .

İşçiye istediğimiz ekstra işlev bağımlılıklarını sadece bir dizide toplayıp dizelere indirgemek için her birinde .toString komutunu çalıştırabileceğimizi unutmayın (işlev bildirimleri olduğu sürece çalışmalıdır) ve daha sonra bunu script dizesine ekler. Bu şekilde, zaten yazdığımız kodun kapsamına dahil etmiş olabileceğimiz importScripts'i almak zorunda kalmıyoruz.

Bu özel versiyonun tek dezavantajı, linterlerin "ayrı işçi fonksiyonu yaklaşımı" için bir avantaj olan hizmet işçisi kodunu (sadece bir dize olduğu için) tiftik edemeyeceğidir.


1

Bu sadece yukarıda bir ektir - jsFiddle web çalışanları test etmek için güzel bir şablon var. Blob yerine jsFiddles ?jsapi kullanır :

function workerFN() {
  self.onmessage = function(e) {
    switch(e.data.name) {
      case "" : 
      break;
      default:
        console.error("Unknown message:", e.data.name);
    }
  }
}
// This is a trick to generate real worker script that is loaded from server
var url = "/echo/js/?js="+encodeURIComponent("("+workerFN.toString()+")()");
var worker = new Worker(url);
worker.addEventListener("message", function(e) {
  switch(e.data.name) {
    case "" : 
    break;
    default:
      console.error("Unknown message:", e.data.name);
  }
})

Normal web çalışanı ve paylaşılan çalışan şablonları kullanılabilir.


1

CodePen şu anda <script>olmayan type="text/javascript"(veya hiçbir türü özniteliği) satır içi etiketleri sözdizimi vurgulamak olmadığını keşfetti .

Yani kullanarak benzer ancak biraz daha farklı bir çözüm geliştirdi etiketli blokları ile breakbir kurtuldun tek yolu, <script>(gereksiz) bir sarıcı işlevi yaratmadan etiketi.

<!DOCTYPE html>
<script id="worker1">
  worker: { // Labeled block wrapper

    if (typeof window === 'object') break worker; // Bail if we're not a Worker

    self.onmessage = function(e) {
      self.postMessage('msg from worker');
    };
    // Rest of your worker code goes here.
  }
</script>
<script>
  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) {
    console.log("Received: " + e.data);
  }
  worker.postMessage("hello"); // Start the worker.
</script>


1

Bir Function#callAsWorkerthisArg ve bağımsız değişkenler (tıpkı gibi call) alan ve bir söz veren basit bir söz verilen sürüm.

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);
});


close()web çalışanınızın can kancasını kapatmak için yöntem eklemeniz gerekir . developer.mozilla.org/tr-TR/docs/Web/API/WorkerGlobalScope/…
Shahar ド ー ン Levi

@Shahar ド ー ン Levi, closeişlev kullanımdan kaldırıldı. Ancak işçiler feshedilebilir . Bunu şimdi ekledim.
19'da trincot

0

Ben böyle kod kullanın, onmessage düz metin dışında bir işlev olarak tanımlayabilirsiniz, böylece editör kodunuzu vurgulamak ve jshint çalışır.

const worker = createWorker();

createWorker() {
    const scriptContent = getWorkerScript();
    const blob = new Blob([
        scriptContent,
    ], {
        type: "text/javascipt"
    });
    const worker = new Worker(window.URL.createObjectURL(blob));
    return worker;
}

getWorkerScript() {
    const script = {
        onmessage: function (e) {
            console.log(e);
            let result = "Hello " + e.data
            postMessage(result);
        }
    };
    let content = "";
    for (let prop in script){
        content += `${prop}=${script[prop].toString()}`;
    }
    return content;
}


Benim bak cevap , sadece yaptım ama geri aramalar nasıl geçirileceği soyutlayarak için bütün sınıf yazdı
Fernando Carvajal

0

Evet, mümkün, Blob dosyalarını kullanarak ve bir geri arama geçirerek yaptım

Size yazdığım bir sınıfın ne yaptığını ve geri aramaların arka planda yürütülmesini nasıl yönettiğini göstereceğim.

Öncelikle , kullanmak istediğiniz işlevleri, bu durumda bir sayı, bir tarih ve çağrılan bir işlevi içeren, GenericWebWorkergeri çağrıya iletmek istediğiniz verileri kullanarakWeb Workerblocker

var worker = new GenericWebWorker(100, new Date(), blocker)

Bu engelleyici işlevi n milisaniye boyunca sonsuz yürütür

function blocker (ms) {
    var now = new Date().getTime();
    while(true) {
        if (new Date().getTime() > now +ms)
            return;
    }   
}

ve sonra böyle kullanıyorsun

worker.exec((num, date, fnBlocker) => {
    /*Everithing here does not block the main thread
      and this callback has access to the number, date and the blocker */
    fnBlocker(10000) //All of this run in backgrownd
    return num*10

}).then(d => console.log(d)) //Print 1000

Şimdi, aşağıdaki örnekte sihri görme zamanı

/*https://github.com/fercarvo/GenericWebWorker*/
class GenericWebWorker {
    constructor(...ags) {
        this.args = ags.map(a => (typeof a == 'function') ? {type:'fn', fn:a.toString()} : a)
    }

    async exec(cb) {
        var wk_string = this.worker.toString();
        wk_string = wk_string.substring(wk_string.indexOf('{') + 1, wk_string.lastIndexOf('}'));            
        var wk_link = window.URL.createObjectURL( new Blob([ wk_string ]) );
        var wk = new Worker(wk_link);

        wk.postMessage({ callback: cb.toString(), args: this.args });
 
        var resultado = await new Promise((next, error) => {
            wk.onmessage = e => (e.data && e.data.error) ? error(e.data.error) : next(e.data);
            wk.onerror = e => error(e.message);
        })

        wk.terminate(); window.URL.revokeObjectURL(wk_link);
        return resultado
    }

    async parallel(arr, cb) {
        var res = [...arr].map(it => new GenericWebWorker(it, ...this.args).exec(cb))
        var all = await Promise.all(res)
        return all
    }

    worker() {
        onmessage = async function (e) {
            try {                
                var cb = new Function(`return ${e.data.callback}`)();
                var args = e.data.args.map(p => (p.type == 'fn') ? new Function(`return ${p.fn}`)() : p);

                try {
                    var result = await cb.apply(this, args); //If it is a promise or async function
                    return postMessage(result)

                } catch (e) { throw new Error(`CallbackError: ${e}`) }
            } catch (e) { postMessage({error: e.message}) }
        }
    }
}


function blocker (ms) {
    var now = new Date().getTime();
    while(true) {
        if (new Date().getTime() > now +ms)
            return;
    }   
}

setInterval(()=> console.log("Not blocked " + Math.random()), 1000)

console.log("\n\nstarting blocking code in Worker\n\n")

var worker = new GenericWebWorker(100, new Date(), blocker)

worker.exec((num, date, fnBlocker) => {
    fnBlocker(7000) //All of this run in backgrownd
    return num*10    
})
.then(d => console.log(`\n\nEnd of blocking code: result ${d}\n\n`)) //Print 1000


0

Worker.js dosyanızın içeriğini backticks içine yerleştirebilirsiniz (çok satırlı dize sabitine izin verir) ve çalışanı aşağıdaki gibi bir blobdan oluşturabilirsiniz:

var workerScript = `
    self.onmessage = function(e) {
        self.postMessage('message from worker');
    };
    // rest of worker code goes here
`;

var worker =
    new Worker(createObjectURL(new Blob([workerScript], { type: "text/javascript" })));

Herhangi bir nedenle çalışan için ayrı komut dosyası etiketlerine sahip olmak istemiyorsanız bu kullanışlıdır.


0

Başka bir çözüm, İşçiyi bir işleve sarmak, ardından işlevi böyle çağıran bir damla oluşturmaktır:

     function workerCode() {
        self.onmessage = function (e) {
          console.log("Got message from parent", e.data);
        };
        setTimeout(() => {
          self.postMessage("Message From Worker");
        }, 2000);
      }

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

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

-1

İşçilerin işlevlerini çalıştırmak için tek astar:

const FunctionalWorker = fn => new Worker(window.URL.createObjectURL(new Blob(["(" + workerCode.toString() + ")()"], {type: "text/javascript"})));

Örnek kullanım:

let fn = FunctionalWorker(() => {
    self.postMessage("hi");
});
fn.onmessage = msg => {
    console.log(msg);
};
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.