How to Create a Web Worker from a String

How to create a Web Worker from a string

Summary


  • blob: for Chrome 8+, Firefox 6+, Safari 6.0+, Opera 15+
  • data:application/javascript for Opera 10.60 - 12
  • eval otherwise (IE 10+)

URL.createObjectURL(<Blob blob>) can be used to create a Web worker from a string. The blob can be created using the BlobBuilder API deprecated or the Blob constructor.

Demo: http://jsfiddle.net/uqcFM/49/

// URL.createObjectURL
window.URL = window.URL || window.webkitURL;

// "Server response", used in all examples
var response = "self.onmessage=function(e){postMessage('Worker: '+e.data);}";

var blob;
try {
blob = new Blob([response], {type: 'application/javascript'});
} catch (e) { // Backwards-compatibility
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
blob = new BlobBuilder();
blob.append(response);
blob = blob.getBlob();
}
var worker = new Worker(URL.createObjectURL(blob));

// Test, used in all examples:
worker.onmessage = function(e) {
alert('Response: ' + e.data);
};
worker.postMessage('Test');

Compatibility

Web workers are supported in the following browsers source:

  • Chrome 3
  • Firefox 3.5
  • IE 10
  • Opera 10.60
  • Safari 4

This method's support is based on the support of the Blob API and the URL.createObjectUrl method. Blob compatibility:

  • Chrome 8+ (WebKitBlobBuilder), 20+ (Blob constructor)
  • Firefox 6+ (MozBlobBuilder), 13+ (Blob constructor)
  • Safari 6+ (Blob constructor)

IE10 supports MSBlobBuilder and URL.createObjectURL. However, trying to create a Web Worker from a blob:-URL throws a SecurityError.

Opera 12 does not support URL API. Some users may have a fake version of the URL object, thanks to this hack in browser.js.

Fallback 1: data-URI

Opera supports data-URIs as an argument to the Worker constructor. Note: Do not forget to escape special characters (Such as # and %).

// response as defined in the first example
var worker = new Worker('data:application/javascript,' +
encodeURIComponent(response) );
// ... Test as defined in the first example

Demo: http://jsfiddle.net/uqcFM/37/

Fallback 2: Eval

eval can be used as a fallback for Safari (<6) and IE 10.

// Worker-helper.js
self.onmessage = function(e) {
self.onmessage = null; // Clean-up
eval(e.data);
};
// Usage:
var worker = new Worker('Worker-helper.js');
// `response` as defined in the first example
worker.postMessage(response);
// .. Test as defined in the first example

Web workers without a separate Javascript file?

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

What if you want to create your worker script on the fly, or create a self-contained page without having to create separate worker files? With Blob(), you can "inline" your worker in the same HTML file as your main logic by creating a URL handle to the worker code as a string



Full example of BLOB inline worker:

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

How can I load a shared web worker with a user-script?

You can use fetch(), response.blob() to create an Blob URL of type application/javascript from returned Blob; set SharedWorker() parameter to Blob URL created by URL.createObjectURL(); utilize window.open(), load event of newly opened window to define same SharedWorker previously defined at original window, attach message event to original SharedWorker at newly opened windows.

javascript was tried at console at How to clear the contents of an iFrame from another iFrame, where current Question URL should be loaded at new tab with message from opening window through worker.port.postMessage() event handler logged at console.

Opening window should also log message event when posted from newly opened window using worker.postMessage(/* message */), similarly at opening window

window.worker = void 0, window.so = void 0;

fetch("https://cdn.rawgit.com/viziionary/Nacho-Bot/master/webworker.js")
.then(response => response.blob())
.then(script => {
console.log(script);
var url = URL.createObjectURL(script);
window.worker = new SharedWorker(url);
console.log(worker);
worker.port.addEventListener("message", (e) => console.log(e.data));
worker.port.start();

window.so = window.open("https://stackoverflow.com/questions/"
+ "38810002/"
+ "how-can-i-load-a-shared-web-worker-"
+ "with-a-user-script", "_blank");

so.addEventListener("load", () => {
so.worker = worker;
so.console.log(so.worker);
so.worker.port.addEventListener("message", (e) => so.console.log(e.data));
so.worker.port.start();
so.worker.port.postMessage("hi from " + so.location.href);
});

so.addEventListener("load", () => {
worker.port.postMessage("hello from " + location.href)
})

});

At console at either tab you can then use, e.g.; at How to clear the contents of an iFrame from another iFrame worker.postMessage("hello, again") at new window of current URL How can I load a shared web worker with a user-script?, worker.port.postMessage("hi, again"); where message events attached at each window, communication between the two windows can be achieved using original SharedWorker created at initial URL.

Is there a way to render an SVG string to an OffscreenCanvas in a web worker?

No native way yet.

Per the specs, you should be able to create an ImageBitmap from a Blob holding your SVG image even in a Worker.

In reality, no browser has implemented it, and when I talked about it with the implementers, it seems it's not on anyone's track to do so.

In Chrome you have access to the Path2D constructor, which can somehow help with <path>'s d attributes, but that's really just a very small part of rendering an SVG.

So the best will probably be to use a library for this.

Notabily, I think canvg is the most appropriate here. I don't use it myself but they're here for a long time now, and it seems the latest version does work with OffscreenCanvas in a Worker (in Chrome).

Create a Web Worker from a Chrome Extension content script

http://crbug.com/357664 is the bug report about not being able to load extension scripts as a web worker.

The workaround to this problem is to load the worker script using XMLHttpRequest, then load the worker from a string. When I faced this problem in the past, I created a wrapper that transparently modifies the Worker constructor, so you can use new Worker(chrome.runtime.getURL('worker.js')) without any problems.

See patch-worker.js (documentation) for the implementation of the previous idea.

patch-worker.js has some limitations (e.g. importScripts does not work as expected), mainly related to the fact that it does not run in the chrome-extension:-origin. To solve these problems, I created another library that uses an iframe to create the Worker. See worker_proxy for the source code and documentation.

Make a function run via web workers

You can inline a web worker as a blob without using a separate file:

<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" });
var worker = new Worker(window.URL.createObjectURL(blob));
worker.onmessage = function(e) {
console.log("Received: " + e.data);
}
worker.postMessage("hello");
// Start the worker
</script>

Note that browser support might not be as robust with this method.

See here for additional details: https://stackoverflow.com/a/6454685/5535081

plainToClass to call object.method() in web worker thread

Passing data to a Web worker is done by serializing the object, so you won't be able to pass in behavior. Instead, you'll need to either use plainToClass as you have in your example, or you can provide the functionality in a helper function.

Additionally, import reflect-metadata is an import for side-effects. This code is run once per context, so it will need to be run again inside the worker, and then plainToClass should work.

That said, a simpler approach might be to try to call the class constructor using the values passed in - if that’s possible?



Related Topics



Leave a reply



Submit