एक अलग जावास्क्रिप्ट फ़ाइल के बिना वेब कार्यकर्ता?


291

जहाँ तक मैं बता सकता हूँ, वेब कर्मचारियों को एक अलग जावास्क्रिप्ट फ़ाइल में लिखने की जरूरत है, और इसे इस तरह कहा जाता है:

new Worker('longrunning.js')

मैं अपने सभी जावास्क्रिप्ट स्रोत कोड को संयोजित करने और उन्हें छोटा करने के लिए क्लोजर कंपाइलर का उपयोग कर रहा हूं, और मुझे वितरण के लिए अलग-अलग फाइलों में अपने श्रमिकों को नहीं रखना पड़ेगा। क्या ऐसा करने का कोई तरीका है?

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

यह देखते हुए कि प्रथम श्रेणी के कार्य जावास्क्रिप्ट के लिए बहुत महत्वपूर्ण हैं, पृष्ठभूमि कार्य करने का मानक तरीका वेब सर्वर से पूरी तरह से अन्य जावास्क्रिप्ट फ़ाइल को लोड करना क्यों है?


7
ऐसा इसलिए है क्योंकि एक निष्पादन संदर्भ को विशुद्ध रूप से थ्रेडसेफ़ रखना प्रथम श्रेणी के कार्यों की तुलना में कहीं अधिक महत्वपूर्ण है :-)
पॉइन्टी

1
मैं इस पर काम कर रहा हूं (या समस्या को कम करने के बजाय): डायनेवर । आप कर सकते हैं: var worker = new DynWorker(); worker.inject("foo", function(){...});...
Félix Saparelli


1
ओपी ने "टीचिंग वर्कर को जावास्क्रिप्ट सोर्स फाइल के बजाय फंक्शन स्वीकार करने के लिए डिलीट कर दिया" सवाल। इसका उत्तर यहाँ दिया गया है
रोब डब्ल्यू

मैंने टास्क विकसित किया है। इसे करने के लिए बहुत आसान बनाना है। अधिकांश समय आप केवल छोटे लॉकिंग कार्यों को बंद करने का प्रयास कर रहे हैं।
चाड Scira

जवाबों:


225

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

क्या होगा यदि आप मक्खी पर अपने कार्यकर्ता की स्क्रिप्ट बनाना चाहते हैं, या अलग-अलग कार्यकर्ता फ़ाइलों को बनाने के बिना एक स्व-निहित पृष्ठ बनाना चाहते हैं? ब्लॉब () के साथ, आप अपने कार्यकर्ता को उसी मुख्य फ़ाइल के रूप में उसी कोड में "इनलाइन" कर सकते हैं, जो स्ट्रिंग के रूप में वर्कर कोड को URL हैंडल बनाकर देता है।


BLOB इनलाइन कार्यकर्ता का पूर्ण उदाहरण:

<!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>


Google Chrome केवल समाधान, लगता है फ़ायरफ़ॉक्स 10 इसका समर्थन करेगा, मुझे अन्य ब्राउज़रों के बारे में पता नहीं है
4esn0k

2
BlobBuiler अब पदावनत हो गया है । इसके बजाय बूँद का उपयोग करें । वर्तमान में नवीनतम फ़ायरफ़ॉक्स / वेबिट / ओपेरा और IE10 में समर्थित है, पुराने ब्राउज़रों के लिए संगतता टेबल देखें ।
फेलिक्स सपरेली

3
IE10 में ब्लॉब कंस्ट्रक्टर का समर्थन किया जा सकता है, लेकिन आप अभी भी इसके माध्यम से वेब कार्यकर्ता को जावास्क्रिप्ट नहीं दे सकते हैं (IE11 में भी नहीं): connect.microsoft.com/IE/feedback/details/801810/…
जयरोज़ो

1
@albanx- परीक्षण क्या है? ऑनलाइन पहले से ही बिलियन डेमो पेज हैं जो दिखाता है कि थ्रेडिंग सालों तक ब्राउज़र को हैंग नहीं करता है।
vsync

2
@albanx - क्या आप कम से कम यह कहने की परवाह करेंगे कि आप कौन सा गूढ़ ब्राउज़र प्रयोग करते हैं जो लटका हुआ है? क्या यह डेमो आपके लिए लटका है? ie.microsoft.com/testdrive/Graphics/WorkerFountains/…
vsync

162

HTML में वेब वर्कर कोड को एम्बेड करने का html5rocks समाधान काफी भयानक है।
और बच गए जावास्क्रिप्ट-ए-ए-स्ट्रिंग का एक बूँद बेहतर नहीं है, कम से कम नहीं क्योंकि यह काम-प्रवाह को जटिल करता है (क्लोजर कंपाइलर तार पर काम नहीं कर सकता है)।

व्यक्तिगत रूप से मैं वास्तव में। तरीके की तरह है, लेकिन @ दान आदमी regex!

मेरा पसंदीदा तरीका:

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

समर्थन इन तीन तालिकाओं का प्रतिच्छेदन है:

हालाँकि, यह एक SharedWorker के लिए काम नहीं करेगा , क्योंकि URL एक सटीक मिलान होना चाहिए, भले ही वैकल्पिक 'नाम' पैरामीटर मेल खाता हो। SharedWorker के लिए, आपको एक अलग जावास्क्रिप्ट फ़ाइल की आवश्यकता होगी।


2015 अद्यतन - ServiceWorker विलक्षणता आती है

अब इस समस्या को हल करने का एक और अधिक शक्तिशाली तरीका है। फिर से, कार्यकर्ता कोड को एक फ़ंक्शन के रूप में संग्रहीत करें, (एक स्थिर स्ट्रिंग के बजाय) और .toString () का उपयोग करके परिवर्तित करें, फिर अपनी पसंद के स्थिर URL के तहत कोड को CacheStorage में डालें।

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

दो संभावित पतन-पीठ हैं। उपरोक्तानुसार ऑब्जेक्ट, या अधिक मूल रूप से, /my_workers/worker1.js पर एक वास्तविक जावास्क्रिप्ट फ़ाइल डालें

इस दृष्टिकोण के लाभ हैं:

  1. SharedWorkers का भी समर्थन किया जा सकता है।
  2. टैब्स एक तय पते पर एक ही कैश्ड कॉपी साझा कर सकते हैं। बूँद दृष्टिकोण हर टैब के लिए यादृच्छिक objectURL का प्रसार करता है।

4
इस समाधान पर ब्राउज़र संगतता क्या दिखेगी?
बेन दिल्ट्स

क्या आप इस समाधान के बारे में विस्तार से बता सकते हैं कि यह कैसे काम करता है? कार्यकर्ता १.जज क्या है? यह एक अलग js फ़ाइल है? मैं इसका उपयोग करने की कोशिश कर रहा हूं लेकिन यह काम करने में असमर्थ है। विशेष रूप से मैं एक SharedWorker के लिए यह काम करने के लिए कोशिश कर रहा हूँ
Yehuda

यदि केवल आप इसे एक उपयोगी फ़ंक्शन में लपेट सकते हैं!
mmm

@ बेन दिल्ट्स: ब्राउज़र संगतता बबल
Jack Giffin

मानक कार्य नहीं करता है जो Function.prototype.toString () फ़ंक्शन बॉडी को स्ट्रिंग के रूप में लौटाता है। आपको उत्तर के लिए एक चेतावनी जोड़ना चाहिए।
आरडी

37

आप एक एकल जावास्क्रिप्ट फ़ाइल बना सकते हैं जो इसके निष्पादन संदर्भ से अवगत है और यह एक मूल स्क्रिप्ट और एक कार्यकर्ता दोनों के रूप में कार्य कर सकती है। इस तरह से एक फाइल के लिए एक बुनियादी संरचना के साथ शुरू करते हैं:

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

जैसा कि आप देख सकते हैं, स्क्रिप्ट में माता-पिता और कार्यकर्ता के दृष्टिकोण दोनों के लिए सभी कोड होते हैं, यह जांचने के लिए कि क्या इसका व्यक्तिगत उदाहरण एक कार्यकर्ता है !document। कुछ हद तक अनजाने script_pathअभिकलन का उपयोग मूल पृष्ठ के सापेक्ष स्क्रिप्ट के पथ की सही गणना करने के लिए किया जाता है, क्योंकि जिस पथ को आपूर्ति की new Workerजाती है वह मूल पृष्ठ के सापेक्ष होता है, स्क्रिप्ट के नहीं।


4
आपकी साइट गायब हो गई प्रतीत होती है; क्या आपके पास एक नया URL है?
ब्रायनफ्रेड जूड

1
यह एक दिलचस्प दृष्टिकोण है। एफडब्ल्यूआईडब्ल्यू, मैं "स्वयं" (वेब ​​वर्कर ग्लोबल ऑब्जेक्ट) बनाम "विंडो" की उपस्थिति की जांच करके वेब वर्कर्स का पता लगाता हूं।
13'13

मैं देख रहा हूँ कि कैसे PapaParse वेब वर्कर्स को संभालता है और वे इस दृष्टिकोण को लेने लगते हैं github.com/mholt/PapaParse
JP DeVries

मुझे लगता है कि 'टाइपो आयात' का उपयोग करके परीक्षण करना! == अशक्त 'यह बता सकता है कि स्क्रिप्ट कार्यकर्ता के दायरे में चल रही है या नहीं।
MeTTeO

1
मुझे समझ नहीं आ रहा है कि स्क्रिप्ट-एलिमेंट से पिछले सिब्लिंग क्या है। क्या कोई मुझे समझा सकता है?
तेमोह

28

Blobविधि का उपयोग करना , श्रमिक कारखाने के लिए इस बारे में कैसे:

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

तो आप इसे इस तरह से उपयोग कर सकते हैं ...

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

संपादित करें:

मैंने अभी इस विचार को आगे बढ़ाया है ताकि क्रॉस-थ्रेड संचार करना आसान हो सके: ब्रिजेड-वर्कर.जेएस

संपादित करें 2:

उपरोक्त लिंक मेरे द्वारा बनाए गए जिस्ट का है। बाद में किसी और ने इसे वास्तविक रेपो में बदल दिया ।


11

वेब कार्यकर्ता व्यक्तिगत कार्यक्रम के रूप में पूरी तरह से अलग संदर्भों में काम करते हैं।

इसका मतलब यह है कि कोड को वस्तु के रूप में एक संदर्भ से दूसरे संदर्भ में नहीं ले जाया जा सकता है, क्योंकि वे तब वस्तुओं को संदर्भ के माध्यम से दूसरे संदर्भ से जोड़ पाएंगे।
यह विशेष रूप से महत्वपूर्ण है क्योंकि ECMAScript को एक एकल थ्रेडेड भाषा के रूप में डिज़ाइन किया गया है, और चूंकि वेब कर्मचारी अलग-अलग थ्रेड में काम करते हैं, इसलिए आपको गैर-थ्रेड-सुरक्षित संचालन का जोखिम होगा।

यह फिर से मतलब है कि वेब कर्मचारियों को स्रोत रूप में कोड के साथ आरंभ करने की आवश्यकता है।

WHATWG से युक्ति कहती है

यदि परिणामी निरपेक्ष URL की उत्पत्ति प्रविष्टि स्क्रिप्ट की उत्पत्ति के समान नहीं है, तो SECURITY_ERR अपवाद को फेंक दें।

इस प्रकार, लिपियों में मूल पृष्ठ जैसी ही स्कीम वाली बाहरी फाइलें होनी चाहिए: आप किसी स्क्रिप्ट को डेटा से लोड नहीं कर सकते: URL या जावास्क्रिप्ट: URL, और https: पृष्ठ http: URL के साथ स्क्रिप्ट का उपयोग करके श्रमिकों को शुरू नहीं कर सकते।

लेकिन दुर्भाग्य से यह वास्तव में व्याख्या नहीं करता है कि किसी ने स्रोत कोड के साथ स्ट्रिंग को निर्माणकर्ता को पारित करने की अनुमति क्यों नहीं दी।


6

एक इनलाइन कर्मचारी के लिए बेहतर तरीके से पढ़ने के लिए ।।

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

मैंने जो किया वह यह था कि मैंने सभी कार्यकर्ता कोड के साथ एक फंक्शन बनाया, उस फंक्शन को पास किया toString(), बॉडी को एक्स्ट्रा किया और फिर एक ब्लॉब में रखा। अंतिम उत्तर पर जाँच करें, मेरे पास एक उदाहरण है
फर्नांडो कार्वाजल

5

एड्रिया की प्रतिक्रिया लेते हुए और इसे कॉपी-पेस्ट करने योग्य फ़ंक्शन में डाल दिया जाता है जो वर्तमान क्रोम और एफएफ के साथ काम करता है, लेकिन IE10 नहीं है (बूँद से कार्यकर्ता एक सुरक्षा त्रुटि का कारण बनता है )।

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

और यहाँ एक काम कर उदाहरण http://jsfiddle.net/ubershmekel/YYzvr/ है


5

हालिया उत्तर (2018)

आप ग्रीनलेट का उपयोग कर सकते हैं :

अपने स्वयं के थ्रेड में एक async फ़ंक्शन को ले जाएं। वर्कराइज़ का एक सरलीकृत एकल-फ़ंक्शन संस्करण ।

उदाहरण:

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

आपके उपयोग के मामले के आधार पर आप कुछ का उपयोग कर सकते हैं

कार्य .js सभी कोर पर चलाने के लिए सीपीयू गहन कोड प्राप्त करने के लिए सरलीकृत इंटरफ़ेस (नोड। जेएस, और वेब)

एक उदाहरण होगा

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 प्लगइन पर एक नज़र डालें। Htis प्लगइन के साथ आप अपने मुख्य कोड में किसी भी फ़ंक्शन को ले सकते हैं और इसे थ्रेड (वेब ​​वर्कर) में निष्पादित कर सकते हैं। इसलिए, आपको एक विशेष "वेब-वर्कर फ़ाइल" बनाने की आवश्यकता नहीं है।

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

--Vadim


1

आप इनलाइन वेबवर्क का उपयोग करके एक ही जावास्क्रिप्ट फी में वेब कर्मचारियों का उपयोग कर सकते हैं।

नीचे दिए गए लेख आपको वेबवर्क और उनकी सीमाओं और वेबवर्क की डीबगिंग को आसानी से समझने के लिए संबोधित करेंगे।

वेबवर्क में माहिर


1

मुझे लगता है कि ऐसा करने का बेहतर तरीका एक ब्लॉब ऑब्जेक्ट का उपयोग करना है, नीचे आप एक सरल उदाहरण देख सकते हैं।

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

यहाँ कंसोल:

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

इसलिए मुझे लगता है कि हमारे पास अब इसके लिए एक और अच्छा विकल्प है, ES6 में टेम्पलेट शाब्दिक के लिए धन्यवाद। यह हमें अतिरिक्त कार्यकर्ता फ़ंक्शन (और इसके अजीब दायरे) के साथ फैलाने की अनुमति देता है और बस उस कोड को लिखें जो कार्यकर्ता के लिए बहुस्तरीय पाठ के रूप में अभिप्रेत है, उस मामले की तरह, जहां हम पाठ को स्टोर करने के लिए उपयोग कर रहे थे, लेकिन वास्तव में दस्तावेज़ या डोम की आवश्यकता के बिना ऐसा करने के लिए। उदाहरण:

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

यहाँ उस दृष्टिकोण के बाकी हिस्सों का उल्लेख है

ध्यान दें कि हम किसी भी अतिरिक्त फ़ंक्शन निर्भरता में खींच सकते हैं जिसे हम कार्यकर्ता को केवल एक सरणी में इकट्ठा करके और चलाना चाहते हैं। उनमें से प्रत्येक पर उन्हें स्ट्रिंग्स में कम करने के लिए (साथ ही जब तक वे फ़ंक्शन घोषणाएं हैं तब तक काम करना चाहिए)। तो बस स्क्रिप्ट स्ट्रिंग के लिए तैयार है। इस तरह से हमें आयात करने की ज़रूरत नहीं है कि हम जो कोड लिख रहे हैं उसके दायरे में पहले से ही हो सकता है।

इस विशेष संस्करण के लिए केवल वास्तविक पहलू यह है कि लिंटर्स सेवा कार्यकर्ता कोड (क्योंकि यह सिर्फ एक स्ट्रिंग है) को उधार नहीं दे पाएंगे, जो कि "अलग कार्यकर्ता फ़ंक्शन दृष्टिकोण" के लिए एक फायदा है।


1

यह ऊपर का सिर्फ एक जोड़ है - मेरे पास jsFiddle में वेब श्रमिकों के परीक्षण के लिए एक अच्छा खाका है। बूँद के बजाय यह jsFiddles ?jsएपीआई का उपयोग करता है :

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

सामान्य वेब कार्यकर्ता और साझा कार्यकर्ता टेम्पलेट उपलब्ध हैं।


1

मुझे पता चला कि कोडपैन वर्तमान में वाक्य-हाइलाइट इनलाइन <script>टैग नहीं हैं type="text/javascript"(जो किसी भी प्रकार की विशेषता नहीं है)।

इसलिए मैंने लेबल के साथ ब्लॉक का उपयोग करके एक समान लेकिन थोड़ा अलग समाधान तैयार किया break, जो एकमात्र तरीका है जिससे आप <script>एक आवरण फ़ंक्शन बनाए बिना (जो अनावश्यक है) टैग से जमानत कर सकते हैं ।

<!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

एक सरल प्रॉमिस किया गया संस्करण, Function#callAsWorkerजो इस आर्ग और तर्कों (बस की तरह call) लेता है , और एक वादा लौटाता है:

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()अपने वेब वर्कर के जीवन को बंद करने के लिए विधि को जोड़ना चाहिए । developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/…
Shahar

@Shahar S ド ha लेवी, closeसमारोह पदावनत है। हालांकि, श्रमिकों को समाप्त किया जा सकता है । मैंने अब उसे जोड़ा है।
त्रिनकोट

0

मैं इस तरह कोड का उपयोग करता हूं, आप अपने ऑनमेसेज को सादे पाठ के अलावा एक फ़ंक्शन के रूप में परिभाषित कर सकते हैं, इसलिए संपादक आपके कोड और jshint कार्यों को उजागर कर सकता है।

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


मेरे उत्तर को देखो , मैंने अभी-अभी ऐसा किया है, लेकिन मैंने
फर्नांडो कार्वाजल

0

हां, यह संभव है, मैंने इसे बूँद फ़ाइलों का उपयोग करके और कॉलबैक पास करने के लिए किया

मैं आपको दिखाता हूँ कि मैंने क्या लिखा है और यह पृष्ठभूमि में कॉलबैक के निष्पादन को कैसे प्रबंधित करता है।

सबसे पहले आप GenericWebWorkerउस कॉलबैक से गुजरना चाहते हैं जिसे आप कॉलबैक में पास करना चाहते हैं Web Worker, जिसमें आप निष्पादित कर रहे हैं , जिसमें वे फ़ंक्शन शामिल हैं जिनका आप उपयोग करना चाहते हैं, इस मामले में एक नंबर, एक तिथि और एक फ़ंक्शन कहा जाता हैblocker

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

यह अवरोधक फ़ंक्शन एन मिलिसकंड के लिए एक अनंत निष्पादित करेगा

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

और फिर आप इसे इस तरह से उपयोग करते हैं

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

अब, नीचे दिए गए उदाहरण में जादू देखने का समय है

/*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

आप अपने कार्यकर्ता.जेएस फ़ाइल की सामग्री को बैकटिक्स के अंदर रख सकते हैं (जो एक बहुस्तरीय स्ट्रिंग को स्थिर रखने की अनुमति देता है) और इस तरह से एक ब्लॉब से कार्यकर्ता का निर्माण करें:

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

यदि किसी भी कारण से आप कार्यकर्ता के लिए अलग स्क्रिप्ट टैग नहीं चाहते हैं तो यह आसान है।


0

एक और समाधान सिर्फ एक फ़ंक्शन में वर्कर को लपेटने के लिए है, फिर एक फुल इनवोकिंग फंक्शन का निर्माण करना है जैसे:

     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

श्रमिकों में चल रहे कार्यों के लिए वन-लाइनर:

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

उदाहरण का उपयोग:

let fn = FunctionalWorker(() => {
    self.postMessage("hi");
});
fn.onmessage = msg => {
    console.log(msg);
};
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.