별도의 자바 스크립트 파일이없는 웹 워커?


291

내가 알 수있는 한 웹 작업자는 별도의 JavaScript 파일로 작성하고 다음과 같이 호출해야합니다.

new Worker('longrunning.js')

클로저 컴파일러를 사용하여 모든 JavaScript 소스 코드를 결합하고 최소화하고 있으며 배포를 위해 작업자를 별도의 파일로 만들 필요가 없습니다. 이것을 할 수있는 방법이 있습니까?

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

일류 함수가 JavaScript에 매우 중요하기 때문에 백그라운드 작업을 수행하는 표준 방법이 웹 서버에서 다른 JavaScript 파일을 모두로드해야하는 이유는 무엇입니까?


7
실행 컨텍스트를 순수하게 스레드 안전성으로 유지하는 것이 일류 함수보다 훨씬 중요하기 때문입니다
Pointy

1
나는 그것을 해결하고 있거나 문제를 최소화하기 위해 노력하고 있습니다 : DynWorker . 당신은 할 수 있습니다 : var worker = new DynWorker(); worker.inject("foo", function(){...});...
Félix Saparelli


1
OP는 "JavaScript 소스 파일 대신 기능을 수락하도록 가르치는 작업자"질문을 삭제했습니다. 대답은 여기
Rob W

훨씬 쉽게 할 수 있도록 task.js 를 개발 했습니다 . 대부분의 경우 작은 잠금 작업 만 오프로드하려고합니다.
Chad Scira

답변:


225

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

작업자 스크립트를 즉석에서 만들거나 별도의 작업자 파일을 만들지 않고 자체 포함 된 페이지를 만들려면 어떻게해야합니까? Blob ()을 사용하면 작업자 코드에 대한 URL 핸들을 문자열로 만들어 기본 논리와 동일한 HTML 파일에서 작업자를 "인라인"할 수 있습니다


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>


유일한 해결책 구글 크롬,이를 지원하는 파이어 폭스 (10)을 보인다, 내가 다른 브라우저에 대해 알고하지 않습니다
4esn0k

2
BlobBuiler 는 이제 더 이상 사용되지 않습니다 . 대신 Blob 을 사용하십시오 . 최신 Firefox / WebKit / Opera 및 IE10에서 현재 지원되며 이전 브라우저의 호환성 표 를 참조하십시오 .
Félix Saparelli

3
물방울 생성자는 IE10에서 지원 될 수 있습니다,하지만 당신은 여전히 (심지어 IE11에서) 그것을 통해 웹 노동자에 자바 스크립트 전달할 수 없습니다 : connect.microsoft.com/IE/feedback/details/801810/...를 .
jayarjo

1
@albanx-어떤 테스트? 스레딩이 몇 년 동안 브라우저를 끊지 않는다는 것을 보여주는 10 억 개의 데모 페이지가 온라인에 있습니다.
vsync

2
@albanx-적어도 어떤 난해한 브라우저를 사용합니까? 이 데모가 당신을 위해 달려 있습니까? ie.microsoft.com/testdrive/Graphics/WorkerFountains/…
vsync

162

HTML에 웹 워커 코드를 포함시키는 html5rocks 솔루션은 상당히 끔찍합니다.
그리고 이스케이프 된 JavaScript-as-a-string 문자열은 작업 흐름을 복잡하게하기 때문에 더 나쁘지 않습니다 (클로저 컴파일러는 문자열에서 작동 할 수 없음).

개인적으로 나는 toString 메소드를 정말 좋아하지만 @ dan-man 정규식!

내가 선호하는 접근법 :

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

지원은이 세 테이블의 교차점입니다.

그러나 선택적 'name'매개 변수가 일치하더라도 URL이 정확히 일치해야하므로 SharedWorker 에서는 작동하지 않습니다 . SharedWorker의 경우 별도의 JavaScript 파일이 필요합니다.


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

두 가지 가능한 대체가 있습니다. 위와 같이 또는 더 매끄럽게 ObjectURL은 /my_workers/worker1.js에 실제 JavaScript 파일을 넣습니다.

이 방법의 장점은 다음과 같습니다.

  1. SharedWorkers도 지원할 수 있습니다.
  2. 탭은 고정 주소에서 단일 캐시 사본을 공유 할 수 있습니다. Blob 접근 방식은 모든 탭에 대해 임의의 objectURL을 확산시킵니다.

4
이 솔루션에서 브라우저 호환성은 무엇입니까?
Ben Dilts

이 솔루션을 자세히 설명 할 수 있습니까? 어떻게 작동합니까? Worker1.js은 (는) 무엇 이죠? 별도의 js 파일입니까? 이것을 사용하려고하는데 작동시킬 수 없습니다. 특히 나는 SharedWorker을 위해 그것에게 일을 만들려고 노력하고 있어요
예후 다

유용한 기능으로 마무리 할 수 ​​있다면!
mmm

@ Ben Dilts : 브라우저 호환성은 babel : babeljs.io/repl
Jack Giffin을

표준에서는 Function.prototype.toString ()이 함수 본문을 문자열로 반환한다는 것을 보증하지 않습니다. 아마도 대답에 경고를 추가해야합니다.
RD

37

실행 컨텍스트를 인식하고 상위 스크립트와 작업자 역할을 모두 수행 할 수있는 단일 JavaScript 파일을 작성할 수 있습니다. 다음과 같은 파일의 기본 구조부터 시작하겠습니다.

(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이 있습니까?
BrianFreud

1
이것은 흥미로운 접근법입니다. FWIW : "self"(Web Worker 전역 개체)와 "window"의 존재를 확인하여 Web Workers를 검색합니다.
pwnall

PapaParse가 웹 작업자를 처리하는 방법을 살펴 보았으며이 방법을 사용하는 것 같습니다. github.com/mholt/PapaParse
JP DeVries

'typeof importScripts! == null'을 사용하여 테스트하면 스크립트가 작업자 범위에서 실행되고 있는지 알 수 있다고 생각합니다.
MeTTeO

1
이전 Sibling이 script-element에서 무엇인지 이해하지 못합니다. 누군가 나를 설명 할 수 있습니까?
Teemoh

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

편집하다:

교차 스레드 통신을보다 쉽게 ​​수행 할 수 있도록이 아이디어를 더 확장했습니다 : bridged-worker.js .

편집 2 :

위의 링크는 내가 만든 요점에 대한 것입니다. 다른 누군가가 나중에 그것을 실제 저장소 로 바 꾸었습니다 .


11

웹 워커는 개별 프로그램과는 완전히 다른 맥락에서 작동합니다.

이는 코드가 다른 컨텍스트에 속하는 클로저를 통해 개체를 참조 할 수 있기 때문에 한 컨텍스트에서 다른 컨텍스트로 코드를 이동할 수 없음을 의미합니다.
이는 ECMAScript가 단일 스레드 언어로 설계 되었기 때문에 특히 중요하며 웹 작업자는 별도의 스레드로 작동하므로 스레드로부터 안전하지 않은 작업이 수행 될 위험이 있습니다.

이것은 다시 웹 워커가 소스 형식의 코드로 초기화되어야 함을 의미합니다.

WHATWG 의 사양에 따르면

결과 절대 URL의 원점이 입력 스크립트의 원점과 동일하지 않은 경우 SECURITY_ERR 예외를 발생시킵니다.

따라서 스크립트는 원본 페이지와 동일한 체계를 가진 외부 파일이어야합니다. 데이터 : URL 또는 javascript : 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()하고 본문을 익힌 다음 Blob에 넣는 것입니다. 마지막 답변을 확인하십시오. 예가 있습니다.
Fernando Carvajal

5

Adria의 응답을 취하여 현재 Chrome 및 FF에서는 작동하지만 IE10에서는 작동하지 않는 복사 가능한 복사 가능 기능에 넣습니다 (blob의 작업자는 보안 오류 발생 ).

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)

Greenlet 을 사용할 수 있습니다 .

비동기 함수를 자체 스레드로 이동하십시오. Workerize 의 간단한 단일 기능 버전입니다 .

예:

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

사용 사례에 따라 다음과 같은 것을 사용할 수 있습니다.

task.js 모든 코어 (node.js 및 웹)에서 CPU 집약적 코드를 실행하기위한 단순화 된 인터페이스

예를 들면

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

이 작업을 수행하는 더 좋은 방법은 Blob 개체를 사용하는 것입니다. 아래에서 간단한 예를 볼 수 있습니다.

// 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의 템플릿 리터럴 덕분에 이제 또 다른 멋진 옵션이 있다고 생각합니다. 이를 통해 추가 작업자 기능 (및 이상한 범위)을 생략하고 텍스트를 저장하는 데 사용하는 것과 매우 유사하지만 실제로 문서 또는 DOM이 필요없는 여러 줄 텍스트로 작업자를위한 코드를 작성할 수 있습니다 그것을하기 위해. 예 :

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

나머지 접근 방식요지는 다음과 같습니다 .

우리는 배열에 그것들을 모아서 .toString을 실행하여 그것들을 문자열로 줄임으로써 (함수 선언이라면 작동해야 함) 작업자에게 원하는 추가 함수 종속성을 가져올 수 있습니다. 그런 다음 스크립트 문자열 앞에 추가하십시오. 그렇게하면 이미 작성중인 코드의 범위에 이미 포함되어있는 스크립트를 가져올 필요가 없습니다.

이 특정 버전의 유일한 단점은 linter가 서비스 워커 코드를 보풀 수 없다는 것입니다 (문자열이기 때문에) "별도의 작업자 함수 접근"의 이점입니다.


1

이것은 위의 추가 사항입니다-jsFiddle에서 웹 작업자를 테스트하기위한 멋진 템플릿이 있습니다. Blob 대신 jsFiddles ?jsAPI를 사용합니다 .

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

CodePen이 현재 (또는 속성이없는) 인라인 <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

간단한 promisified 버전, Function#callAsWorkerthisArg 및 인수를 (단지 같은 소요 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 ド ー ン Levi,이 close기능은 더 이상 사용되지 않습니다. 그러나, 근로자 수 있습니다 종료 . 나는 지금 그것을 추가했다.
trincot

0

나는 이와 같은 코드를 사용한다. onmessage를 일반 텍스트 이외의 함수로 정의 할 수 있으므로 편집기가 코드를 강조 표시하고 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

예, 가능합니다 .Blob 파일을 사용하여 콜백을 전달했습니다.

필자가 작성한 클래스의 기능과 백그라운드에서 콜백 실행을 관리하는 방법을 보여 드리겠습니다.

먼저 GenericWebWorker에서 실행할 콜백에 전달할 데이터를 사용 하여를 인스턴스화합니다. Web Worker여기에는 사용하려는 함수 (이 경우 숫자, 날짜 및 함수)가 포함됩니다.blocker

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

이 차단 기능은 n 밀리 초 동안 무한대로 실행됩니다

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

worker.js 파일의 내용을 backticks 안에 넣고 (여러 줄 문자열 상수 허용) 다음과 같이 blob에서 worker를 만들 수 있습니다.

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

또 다른 해결책은 Worker를 함수로 감싸고 다음과 같이 함수를 호출하는 Blob을 만드는 것입니다.

     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);
};
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.