Skip to content Skip to sidebar Skip to footer

Run a Script Agains a Web Page

Using Web Workers

Spider web Workers are a uncomplicated means for web content to run scripts in background threads. The worker thread can perform tasks without interfering with the user interface. In addition, they can perform I/O using XMLHttpRequest (although the responseXML and channel attributes are ever null) or fetch (with no such restrictions). Once created, a worker can send letters to the JavaScript code that created it by posting messages to an event handler specified by that code (and vice versa).

This commodity provides a detailed introduction to using web workers.

Web Workers API

A worker is an object created using a constructor (e.g. Worker()) that runs a named JavaScript file — this file contains the code that volition run in the worker thread; workers run in some other global context that is different from the current window. Thus, using the window shortcut to go the current global scope (instead of self) within a Worker volition render an error.

The worker context is represented by a DedicatedWorkerGlobalScope object in the case of dedicated workers (standard workers that are utilized by a unmarried script; shared workers use SharedWorkerGlobalScope). A dedicated worker is only attainable from the script that outset spawned it, whereas shared workers can be accessed from multiple scripts.

You lot tin can run whatever lawmaking you like inside the worker thread, with some exceptions. For case, yous can't directly manipulate the DOM from inside a worker, or utilize some default methods and properties of the window object. But yous can use a big number of items available nether window, including WebSockets, and data storage mechanisms like IndexedDB. See Functions and classes available to workers for more details.

Data is sent between workers and the main thread via a organisation of messages — both sides send their messages using the postMessage() method, and answer to letters via the onmessage consequence handler (the message is independent within the Message event's data attribute.) The information is copied rather than shared.

Workers may, in turn, spawn new workers, equally long as those workers are hosted within the same origin as the parent page. In improver, workers may use XMLHttpRequest for network I/O, with the exception that the responseXML and channel attributes on XMLHttpRequest always return zero.

Dedicated workers

As mentioned above, a dedicated worker is only attainable by the script that called it. In this department nosotros'll discuss the JavaScript found in our Basic dedicated worker example (run dedicated worker): This allows you to enter 2 numbers to be multiplied together. The numbers are sent to a defended worker, multiplied together, and the result is returned to the page and displayed.

This example is rather trivial, only we decided to keep it uncomplicated while introducing yous to basic worker concepts. More than advanced details are covered later on in the commodity.

Worker feature detection

For slightly more than controlled error handling and backwards compatibility, it is a good idea to wrap your worker accessing lawmaking in the following (principal.js):

                                      if                    (window.Worker)                    {                    ...                    }                                  

Spawning a dedicated worker

Creating a new worker is simple. All you demand to practice is call the Worker() constructor, specifying the URI of a script to execute in the worker thread (main.js):

                                      var                    myWorker                    =                    new                    Worker                    (                    'worker.js'                    )                    ;                                  

Sending messages to and from a dedicated worker

The magic of workers happens via the postMessage() method and the onmessage effect handler. When you desire to ship a message to the worker, yous post messages to information technology like this (main.js):

                  first.                    onchange                    =                    function                    (                    )                    {                    myWorker.                    postMessage                    (                    [first.value,                    second.value]                    )                    ;                    console.                    log                    (                    'Message posted to worker'                    )                    ;                    }                    second.                    onchange                    =                    function                    (                    )                    {                    myWorker.                    postMessage                    (                    [first.value,                    2d.value]                    )                    ;                    console.                    log                    (                    'Bulletin posted to worker'                    )                    ;                    }                                  

And so hither we accept two <input> elements represented past the variables first and second; when the value of either is inverse, myWorker.postMessage([first.value,second.value]) is used to transport the value within both to the worker, every bit an array. Yous can transport pretty much annihilation you lot like in the bulletin.

In the worker, we can reply when the message is received past writing an event handler block like this (worker.js):

                                      onmessage                    =                    office                    (                    due east                    )                    {                    console.                    log                    (                    'Bulletin received from principal script'                    )                    ;                    var                    workerResult                    =                    'Result: '                    +                    (east.data[                    0                    ]                    *                    e.information[                    one                    ]                    )                    ;                    console.                    log                    (                    'Posting message back to principal script'                    )                    ;                    postMessage                    (workerResult)                    ;                    }                                  

The onmessage handler allows usa to run some code whenever a message is received, with the bulletin itself being bachelor in the message event's information attribute. Here we multiply together the 2 numbers then use postMessage() again, to postal service the consequence back to the main thread.

Back in the main thread, we employ onmessage again, to answer to the message sent back from the worker:

                  myWorker.                    onmessage                    =                    office                    (                    east                    )                    {                    result.textContent                    =                    e.data;                    console.                    log                    (                    'Message received from worker'                    )                    ;                    }                                  

Here we catch the bulletin event information and set it as the textContent of the result paragraph, then the user can see the result of the adding.

Note: Observe that onmessage and postMessage() need to be hung off the Worker object when used in the principal script thread, just not when used in the worker. This is because, inside the worker, the worker is effectively the global telescopic.

Note: When a bulletin is passed between the principal thread and worker, information technology is copied or "transferred" (moved), not shared. Read Transferring data to and from workers: farther details for a much more thorough explanation.

Terminating a worker

If you need to immediately terminate a running worker from the main thread, you lot can exercise so by calling the worker's cease method:

The worker thread is killed immediately.

Handling errors

When a runtime error occurs in the worker, its onerror event handler is chosen. It receives an event named error which implements the ErrorEvent interface.

The consequence doesn't bubble and is cancelable; to prevent the default action from taking identify, the worker can telephone call the error effect's preventDefault() method.

The error result has the post-obit three fields that are of interest:

bulletin

A human-readable fault message.

filename

The name of the script file in which the error occurred.

lineno

The line number of the script file on which the error occurred.

Spawning subworkers

Workers may spawn more workers if they wish. And so-called sub-workers must be hosted within the same origin as the parent page. Also, the URIs for subworkers are resolved relative to the parent worker'due south location rather than that of the owning folio. This makes it easier for workers to go along track of where their dependencies are.

Importing scripts and libraries

Worker threads accept access to a global function, importScripts(), which lets them import scripts. It accepts zero or more URIs every bit parameters to resource to import; all of the following examples are valid:

                                      importScripts                    (                    )                    ;                    /* imports zippo */                    importScripts                    (                    'foo.js'                    )                    ;                    /* imports just "foo.js" */                    importScripts                    (                    'foo.js'                    ,                    'bar.js'                    )                    ;                    /* imports two scripts */                    importScripts                    (                    '//example.com/hello.js'                    )                    ;                    /* You can import scripts from other origins */                                  

The browser loads each listed script and executes it. Any global objects from each script may so be used past the worker. If the script can't exist loaded, NETWORK_ERROR is thrown, and subsequent code will not be executed. Previously executed code (including code deferred using setTimeout()) will notwithstanding be functional though. Part declarations afterward the importScripts() method are also kept, since these are ever evaluated before the rest of the code.

Notation: Scripts may exist downloaded in any order, but will be executed in the social club in which y'all pass the filenames into importScripts() . This is washed synchronously; importScripts() does non render until all the scripts have been loaded and executed.

A shared worker is accessible by multiple scripts — even if they are beingness accessed by different windows, iframes or even workers. In this department we'll discuss the JavaScript constitute in our Basic shared worker example (run shared worker): This is very like to the bones defended worker instance, except that information technology has ii functions bachelor handled by different script files: multiplying ii numbers, or squaring a number. Both scripts use the same worker to exercise the actual calculation required.

Here we'll concentrate on the differences between defended and shared workers. Note that in this example nosotros have two HTML pages, each with JavaScript applied that uses the same unmarried worker file.

Note: If SharedWorker tin can be accessed from several browsing contexts, all those browsing contexts must share the exact same origin (aforementioned protocol, host, and port).

Note: In Firefox, shared workers cannot be shared between documents loaded in private and non-private windows (problems 1177621).

Spawning a shared worker

Spawning a new shared worker is pretty much the aforementioned every bit with a defended worker, but with a different constructor proper name (run across alphabetize.html and index2.html) — each one has to spin up the worker using lawmaking like the post-obit:

                                      var                    myWorker                    =                    new                    SharedWorker                    (                    'worker.js'                    )                    ;                                  

One big difference is that with a shared worker you take to communicate via a port object — an explicit port is opened that the scripts can employ to communicate with the worker (this is washed implicitly in the example of dedicated workers).

The port connection needs to be started either implicitly by use of the onmessage event handler or explicitly with the beginning() method before any messages can be posted. Calling start() is only needed if the message event is wired upward via the addEventListener() method.

Note: When using the start() method to open the port connexion, it needs to be called from both the parent thread and the worker thread if two-style communication is needed.

Sending letters to and from a shared worker

Now messages tin can be sent to the worker as before, but the postMessage() method has to be invoked through the port object (again, you'll encounter similar constructs in both multiply.js and square.js):

                  squareNumber.                    onchange                    =                    function                    (                    )                    {                    myWorker.port.                    postMessage                    (                    [squareNumber.value,squareNumber.value]                    )                    ;                    console.                    log                    (                    'Bulletin posted to worker'                    )                    ;                    }                                  

Now, on to the worker. There is a flake more complication here equally well (worker.js):

                                      onconnect                    =                    function                    (                    eastward                    )                    {                    var                    port                    =                    east.ports[                    0                    ]                    ;                    port.                    onmessage                    =                    part                    (                    e                    )                    {                    var                    workerResult                    =                    'Outcome: '                    +                    (eastward.data[                    0                    ]                    *                    eastward.data[                    1                    ]                    )                    ;                    port.                    postMessage                    (workerResult)                    ;                    }                    }                                  

First, nosotros use an onconnect handler to fire lawmaking when a connection to the port happens (i.e. when the onmessage event handler in the parent thread is setup, or when the showtime() method is explicitly called in the parent thread).

We use the ports attribute of this event object to catch the port and store it in a variable.

Adjacent, we add a message handler on the port to practice the calculation and return the result to the principal thread. Setting up this message handler in the worker thread also implicitly opens the port connection back to the parent thread, then the call to port.outset() is not really needed, as noted higher up.

Finally, dorsum in the main script, we bargain with the message (again, you'll see similar constructs in both multiply.js and square.js):

                  myWorker.port.                    onmessage                    =                    role                    (                    e                    )                    {                    result2.textContent                    =                    e.data;                    panel.                    log                    (                    'Message received from worker'                    )                    ;                    }                                  

When a bulletin comes back through the port from the worker, we insert the calculation outcome inside the advisable result paragraph.

Most thread safety

The Worker interface spawns real Os-level threads, and mindful programmers may be concerned that concurrency tin can cause "interesting" effects in your lawmaking if you aren't careful.

However, since web workers accept carefully controlled communication points with other threads, information technology'southward really very hard to cause concurrency problems. At that place'south no access to non-threadsafe components or the DOM. And yous take to pass specific data in and out of a thread through serialized objects. Then you have to work really hard to cause problems in your lawmaking.

Content security policy

Workers are considered to have their own execution context, distinct from the certificate that created them. For this reason they are, in general, not governed past the content security policy of the document (or parent worker) that created them. So for case, suppose a document is served with the following header:

Content-Security-Policy: script-src 'cocky'                

Amidst other things, this volition preclude any scripts it includes from using eval(). Even so, if the script constructs a worker, code running in the worker's context volition be allowed to utilize eval().

To specify a content security policy for the worker, set a Content-Security-Policy response header for the request which delivered the worker script itself.

The exception to this is if the worker script'due south origin is a globally unique identifier (for example, if its URL has a scheme of data or blob). In this case, the worker does inherit the CSP of the document or worker that created it.

Transferring data to and from workers: further details

Data passed between the master page and workers is copied, not shared. Objects are serialized as they're handed to the worker, and subsequently, de-serialized on the other terminate. The page and worker exercise non share the same case, and then the finish result is that a duplicate is created on each cease. Well-nigh browsers implement this feature as structured cloning.

To illustrate this, allow's create a function named emulateMessage(), which will simulate the behavior of a value that is cloned and non shared during the passage from a worker to the main page or vice versa:

                                      function                    emulateMessage                    (                    vVal                    )                    {                    return                    eval                    (                    '('                    +                    JSON                    .                    stringify                    (vVal)                    +                    ')'                    )                    ;                    }                    // Tests                    // test #one                    var                    example1                    =                    new                    Number                    (                    3                    )                    ;                    panel.                    log                    (                    typeof                    example1)                    ;                    // object                    panel.                    log                    (                    typeof                    emulateMessage                    (example1)                    )                    ;                    // number                    // exam #2                    var                    example2                    =                    truthful                    ;                    console.                    log                    (                    typeof                    example2)                    ;                    // boolean                    console.                    log                    (                    typeof                    emulateMessage                    (example2)                    )                    ;                    // boolean                    // test #iii                    var                    example3                    =                    new                    String                    (                    'Howdy Globe'                    )                    ;                    console.                    log                    (                    typeof                    example3)                    ;                    // object                    console.                    log                    (                    typeof                    emulateMessage                    (example3)                    )                    ;                    // cord                    // test #4                    var                    example4                    =                    {                    'proper name'                    :                    'John Smith'                    ,                    "age"                    :                    43                    }                    ;                    console.                    log                    (                    typeof                    example4)                    ;                    // object                    panel.                    log                    (                    typeof                    emulateMessage                    (example4)                    )                    ;                    // object                    // exam #5                    function                    Animal                    (                    sType,                      nAge                    )                    {                    this                    .type                    =                    sType;                    this                    .age                    =                    nAge;                    }                    var                    example5                    =                    new                    Animal                    (                    'Cat'                    ,                    3                    )                    ;                    warning                    (example5.constructor)                    ;                    // Animal                    alert                    (                    emulateMessage                    (example5)                    .constructor)                    ;                    // Object                                  

A value that is cloned and non shared is called bulletin. As you will probably know by now, messages tin exist sent to and from the main thread by using postMessage(), and the bulletin event's data attribute contains data passed back from the worker.

example.html: (the main page):

                                      var                    myWorker                    =                    new                    Worker                    (                    'my_task.js'                    )                    ;                    myWorker.                    onmessage                    =                    office                    (                    oEvent                    )                    {                    console.                    log                    (                    'Worker said : '                    +                    oEvent.data)                    ;                    }                    ;                    myWorker.                    postMessage                    (                    'ali'                    )                    ;                                  

my_task.js (the worker):

                                      postMessage                    (                    "I\'m working before postMessage(\'ali\')."                    )                    ;                    onmessage                    =                    function                    (                    oEvent                    )                    {                    postMessage                    (                    'Hi '                    +                    oEvent.data)                    ;                    }                    ;                                  

The structured cloning algorithm can take JSON and a few things that JSON tin can't — like circular references.

Passing data examples

Example #1: Advanced passing JSON Data and creating a switching organization

If you lot accept to pass some circuitous data and have to call many unlike functions both on the main page and in the Worker, yous can create a arrangement which groups everything together.

First, nosotros create a QueryableWorker grade that takes the URL of the worker, a default listener, and an error handler, and this class is going to go along track of a listing of listeners and help united states communicate with the worker:

                                      part                    QueryableWorker                    (                    url,                      defaultListener,                      onError                    )                    {                    var                    case                    =                    this                    ,                    worker                    =                    new                    Worker                    (url)                    ,                    listeners                    =                    {                    }                    ;                    this                    .defaultListener                    =                    defaultListener                    ||                    part                    (                    )                    {                    }                    ;                    if                    (onError)                    {worker.onerror                    =                    onError;                    }                    this                    .                    postMessage                    =                    function                    (                    message                    )                    {                    worker.                    postMessage                    (message)                    ;                    }                    this                    .                    cease                    =                    function                    (                    )                    {                    worker.                    terminate                    (                    )                    ;                    }                    }                                  

Then we add the methods of adding/removing listeners:

                                      this                    .                    addListeners                    =                    function                    (                    proper noun,                      listener                    )                    {                    listeners[name]                    =                    listener;                    }                    this                    .                    removeListeners                    =                    office                    (                    proper noun                    )                    {                    delete                    listeners[name]                    ;                    }                                  

Here we allow the worker handle ii simple operations for illustration: getting the difference of two numbers and making an alert after three seconds. In order to reach that nosotros first implement a sendQuery method which queries if the worker actually has the corresponding methods to practice what we want.

                                      /*   This functions takes at to the lowest degree one argument, the method name we want to query.   So nosotros tin pass in the arguments that the method needs.  */                    this                    .                    sendQuery                    =                    office                    (                    )                    {                    if                    (arguments.length                    <                    1                    )                    {                    throw                    new                    TypeError                    (                    'QueryableWorker.sendQuery takes at least one argument'                    )                    ;                    return                    ;                    }                    worker.                    postMessage                    (                    {                    'queryMethod'                    :                    arguments[                    0                    ]                    ,                    'queryMethodArguments'                    :                    Array                    .prototype.                    slice                    .                    telephone call                    (arguments,                    i                    )                    }                    )                    ;                    }                                  

We cease QueryableWorker with the onmessage method. If the worker has the corresponding methods nosotros queried, it should render the name of the corresponding listener and the arguments it needs, we but need to find it in listeners.:

                  worker.                    onmessage                    =                    part                    (                    issue                    )                    {                    if                    (result.information                    instanceof                    Object                    &&                    event.data.                    hasOwnProperty                    (                    'queryMethodListener'                    )                    &&                    event.information.                    hasOwnProperty                    (                    'queryMethodArguments'                    )                    )                    {                    listeners[event.data.queryMethodListener]                    .                    apply                    (instance,                    event.data.queryMethodArguments)                    ;                    }                    else                    {                    this                    .                    defaultListener                    .                    telephone call                    (instance,                    event.data)                    ;                    }                    }                                  

At present onto the worker. Showtime we need to have the methods to handle the 2 elementary operations:

                                      var                    queryableFunctions                    =                    {                    getDifference                    :                    part                    (                    a,                      b                    )                    {                    reply                    (                    'printStuff'                    ,                    a                    -                    b)                    ;                    }                    ,                    waitSomeTime                    :                    function                    (                    )                    {                    setTimeout                    (                    function                    (                    )                    {                    respond                    (                    'doAlert'                    ,                    3                    ,                    'seconds'                    )                    ;                    }                    ,                    3000                    )                    ;                    }                    }                    part                    answer                    (                    )                    {                    if                    (arguments.length                    <                    1                    )                    {                    throw                    new                    TypeError                    (                    'reply - takes at least one statement'                    )                    ;                    return                    ;                    }                    postMessage                    (                    {                    queryMethodListener                    :                    arguments[                    0                    ]                    ,                    queryMethodArguments                    :                    Array                    .prototype.                    slice                    .                    call                    (arguments,                    1                    )                    }                    )                    ;                    }                    /* This method is chosen when primary page calls QueryWorker's postMessage method directly*/                    function                    defaultReply                    (                    bulletin                    )                    {                    // do something                    }                                  

And the onmessage method is now lilliputian:

                                      onmessage                    =                    function                    (                    event                    )                    {                    if                    (upshot.data                    instanceof                    Object                    &&                    event.information.                    hasOwnProperty                    (                    'queryMethod'                    )                    &&                    result.data.                    hasOwnProperty                    (                    'queryMethodArguments'                    )                    )                    {                    queryableFunctions[event.data.queryMethod]                    .                    apply                    (self,                    event.data.queryMethodArguments)                    ;                    }                    else                    {                    defaultReply                    (event.data)                    ;                    }                    }                                  

Here are the full implementation:

example.html (the chief page):

                                                            <!                      doctype                      html                      >                                                                                      <html                      >                                                                                      <head                      >                                                                                      <meta                      charset                                              =                        "UTF-8"                                            />                                                                                      <championship                      >                    MDN Example - Queryable worker                                              </championship                      >                                                                                      <script                      type                                              =                        "text/javascript"                                            >                                                                                      /*       QueryableWorker instances methods:         * sendQuery(queryable function proper name, argument to pass 1, argument to pass 2, etc. etc): calls a Worker'southward queryable function         * postMessage(cord or JSON Data): meet Worker.prototype.postMessage()         * finish(): terminates the Worker         * addListener(name, office): adds a listener         * removeListener(name): removes a listener       QueryableWorker instances properties:         * defaultListener: the default listener executed only when the Worker calls the postMessage() role directly      */                        function                        QueryableWorker                        (                        url,                          defaultListener,                          onError                        )                        {                        var                        instance                        =                        this                        ,                        worker                        =                        new                        Worker                        (url)                        ,                        listeners                        =                        {                        }                        ;                        this                        .defaultListener                        =                        defaultListener                        ||                        role                        (                        )                        {                        }                        ;                        if                        (onError)                        {worker.onerror                        =                        onError;                        }                        this                        .                        postMessage                        =                        function                        (                        bulletin                        )                        {                        worker.                        postMessage                        (bulletin)                        ;                        }                        this                        .                        terminate                        =                        function                        (                        )                        {                        worker.                        stop                        (                        )                        ;                        }                        this                        .                        addListener                        =                        function                        (                        name,                          listener                        )                        {                        listeners[proper noun]                        =                        listener;                        }                        this                        .                        removeListener                        =                        function                        (                        name                        )                        {                        delete                        listeners[name]                        ;                        }                        /*         This functions takes at to the lowest degree 1 argument, the method name we want to query.         Then we tin laissez passer in the arguments that the method needs.       */                        this                        .                        sendQuery                        =                        function                        (                        )                        {                        if                        (arguments.length                        <                        one                        )                        {                        throw                        new                        TypeError                        (                        'QueryableWorker.sendQuery takes at least one argument'                        )                        ;                        return                        ;                        }                        worker.                        postMessage                        (                        {                        'queryMethod'                        :                        arguments[                        0                        ]                        ,                        'queryMethodArguments'                        :                        Array                        .paradigm.                        slice                        .                        phone call                        (arguments,                        ane                        )                        }                        )                        ;                        }                        worker.                        onmessage                        =                        part                        (                        event                        )                        {                        if                        (event.information                        instanceof                        Object                        &&                        event.data.                        hasOwnProperty                        (                        'queryMethodListener'                        )                        &&                        event.data.                        hasOwnProperty                        (                        'queryMethodArguments'                        )                        )                        {                        listeners[event.data.queryMethodListener]                        .                        employ                        (instance,                        effect.data.queryMethodArguments)                        ;                        }                        else                        {                        this                        .                        defaultListener                        .                        call                        (instance,                        consequence.data)                        ;                        }                        }                        }                        // your custom "queryable" worker                        var                        myTask                        =                        new                        QueryableWorker                        (                        'my_task.js'                        )                        ;                        // your custom "listeners"                        myTask.                        addListener                        (                        'printStuff'                        ,                        role                        (                        result                        )                        {                        document.                        getElementById                        (                        'firstLink'                        )                        .parentNode.                        appendChild                        (document.                        createTextNode                        (                        'The deviation is '                        +                        result                        +                        '!'                        )                        )                        ;                        }                        )                        ;                        myTask.                        addListener                        (                        'doAlert'                        ,                        role                        (                        fourth dimension,                          unit                        )                        {                        alert                        (                        'Worker waited for '                        +                        fourth dimension                        +                        ' '                        +                        unit                        +                        ' :-)'                        )                        ;                        }                        )                        ;                                                                                                            </script                      >                                                                                      </head                      >                                                                                      <trunk                      >                                                                                      <ul                      >                                                                                      <li                      >                                                                                      <a                      id                                              =                        "firstLink"                                            href                                              =                        "javascript:myTask.sendQuery('getDifference', 5, three);"                                            >                    What is the deviation betwixt 5 and three?                                              </a                      >                                                                                      </li                      >                                                                                      <li                      >                                                                                      <a                      href                                              =                        "javascript:myTask.sendQuery('waitSomeTime');"                                            >                    Wait iii seconds                                              </a                      >                                                                                      </li                      >                                                                                      <li                      >                                                                                      <a                      href                                              =                        "javascript:myTask.finish();"                                            >                    terminate() the Worker                                              </a                      >                                                                                      </li                      >                                                                                      </ul                      >                                                                                      </body                      >                                                                                      </html                      >                                                      

my_task.js (the worker):

                                      var                    queryableFunctions                    =                    {                    // example #1: get the deviation between two numbers:                    getDifference                    :                    part                    (                    nMinuend,                      nSubtrahend                    )                    {                    reply                    (                    'printStuff'                    ,                    nMinuend                    -                    nSubtrahend)                    ;                    }                    ,                    // example #2: wait 3 seconds                    waitSomeTime                    :                    function                    (                    )                    {                    setTimeout                    (                    office                    (                    )                    {                    reply                    (                    'doAlert'                    ,                    iii                    ,                    'seconds'                    )                    ;                    }                    ,                    3000                    )                    ;                    }                    }                    ;                    // organisation functions                    office                    defaultReply                    (                    message                    )                    {                    // your default PUBLIC function executed just when master page calls the queryableWorker.postMessage() method directly                    // do something                    }                    office                    answer                    (                    )                    {                    if                    (arguments.length                    <                    1                    )                    {                    throw                    new                    TypeError                    (                    'reply - not enough arguments'                    )                    ;                    return                    ;                    }                    postMessage                    (                    {                    'queryMethodListener'                    :                    arguments[                    0                    ]                    ,                    'queryMethodArguments'                    :                    Array                    .prototype.                    piece                    .                    call                    (arguments,                    1                    )                    }                    )                    ;                    }                    onmessage                    =                    function                    (                    oEvent                    )                    {                    if                    (oEvent.data                    instanceof                    Object                    &&                    oEvent.data.                    hasOwnProperty                    (                    'queryMethod'                    )                    &&                    oEvent.data.                    hasOwnProperty                    (                    'queryMethodArguments'                    )                    )                    {                    queryableFunctions[oEvent.data.queryMethod]                    .                    apply                    (cocky,                    oEvent.data.queryMethodArguments)                    ;                    }                    else                    {                    defaultReply                    (oEvent.data)                    ;                    }                    }                    ;                                  

It is possible to switch the content of each mainpage -> worker and worker -> mainpage message. And the property names "queryMethod", "queryMethodListeners", "queryMethodArguments" can be anything equally long as they are consequent in QueryableWorker and the worker.

Passing information by transferring ownership (transferable objects)

Modernistic browsers contain an additional manner to pass certain types of objects to or from a worker with loftier performance. Transferable Objects are transferred from one context to another with a cypher-copy functioning, which results in a vast performance improvement when sending large information sets.

For example, when transferring an ArrayBuffer from your chief app to a worker script, the original ArrayBuffer is cleared and no longer usable. Its content is (quite literally) transferred to the worker context.

                                      // Create a 32MB "file" and fill it.                    var                    uInt8Array                    =                    new                    Uint8Array                    (                    1024                    *                    1024                    *                    32                    )                    ;                    // 32MB                    for                    (                    var                    i                    =                    0                    ;                    i                    <                    uInt8Array.length;                    ++i)                    {                    uInt8Array[i]                    =                    i;                    }                    worker.                    postMessage                    (uInt8Array.buffer,                    [uInt8Array.buffer]                    )                    ;                                  

Embedded workers

In that location is not an "official" manner to embed the code of a worker inside a spider web page, like <script> elements do for normal scripts. But a <script> element that does not have a src attribute and has a type attribute that does not identify an executable MIME type tin can be considered a information block element that JavaScript could employ. "Information blocks" is a more full general feature of HTML5 that can carry almost any textual data. And so, a worker could exist embedded in this manner:

                                                            <!                      DOCTYPE                      html                      >                                                                                      <html                      >                                                                                      <head                      >                                                                                      <meta                      charset                                              =                        "UTF-8"                                            />                                                                                      <title                      >                    MDN Instance - Embedded worker                                              </title                      >                                                                                      <script                      blazon                                              =                        "text/js-worker"                                            >                                                                                      // This script WON'T be parsed by JS engines because its MIME type is text/js-worker.                        var                        myVar                        =                        'Hi World!'                        ;                        // Rest of your worker code goes here.                                                                                                            </script                      >                                                                                      <script                      type                                              =                        "text/javascript"                                            >                                                                                      // This script Volition be parsed by JS engines considering its MIME blazon is text/javascript.                        function                        pageLog                        (                        sMsg                        )                        {                        // Utilise a fragment: browser will only render/reflow once.                        var                        oFragm                        =                        document.                        createDocumentFragment                        (                        )                        ;                        oFragm.                        appendChild                        (document.                        createTextNode                        (sMsg)                        )                        ;                        oFragm.                        appendChild                        (document.                        createElement                        (                        'br'                        )                        )                        ;                        document.                        querySelector                        (                        '#logDisplay'                        )                        .                        appendChild                        (oFragm)                        ;                        }                                                                                                            </script                      >                                                                                      <script                      type                                              =                        "text/js-worker"                                            >                                                                                      // This script WON'T be parsed by JS engines because its MIME type is text/js-worker.                        onmessage                        =                        role                        (                        oEvent                        )                        {                        postMessage                        (myVar)                        ;                        }                        ;                        // Residue of your worker code goes here.                                                                                                            </script                      >                                                                                      <script                      type                                              =                        "text/javascript"                                            >                                                                                      // This script Volition be parsed by JS engines because its MIME blazon is text/javascript.                        // In the past...:                        // blob builder existed                        // ...but at present we use Hulk...:                        var                        blob                        =                        new                        Blob                        (                        Array                        .prototype.                        map                        .                        call                        (document.                        querySelectorAll                        (                        'script[type=\'text\/js-worker\']'                        )                        ,                        function                        (                        oScript                        )                        {                        render                        oScript.textContent;                        }                        )                        ,                        {                        blazon                        :                        'text/javascript'                        }                        )                        ;                        // Creating a new certificate.worker property containing all our "text/js-worker" scripts.                        document.worker                        =                        new                        Worker                        (window.                        URL                        .                        createObjectURL                        (hulk)                        )                        ;                        document.worker.                        onmessage                        =                        function                        (                        oEvent                        )                        {                        pageLog                        (                        'Received: '                        +                        oEvent.data)                        ;                        }                        ;                        // Start the worker.                        window.                        onload                        =                        function                        (                        )                        {                        document.worker.                        postMessage                        (                        ''                        )                        ;                        }                        ;                                                                                                            </script                      >                                                                                      </head                      >                                                                                      <body                      >                                                                                      <div                      id                                              =                        "logDisplay"                                            >                                                                                      </div                      >                                                                                      </body                      >                                                                                      </html                      >                                                      

The embedded worker is now nested into a new custom document.worker property.

It is too worth noting that yous can also catechumen a role into a Blob, then generate an object URL from that blob. For case:

                                      function                    fn2workerURL                    (                    fn                    )                    {                    var                    blob                    =                    new                    Hulk                    (                    [                    '('                    +fn.                    toString                    (                    )                    +                    ')()'                    ]                    ,                    {                    blazon                    :                    'text/javascript'                    }                    )                    return                    URL                    .                    createObjectURL                    (blob)                    }                                  

Further examples

This section provides further examples of how to use spider web workers.

Performing computations in the background

Workers are mainly useful for allowing your code to perform processor-intensive calculations without blocking the user interface thread. In this example, a worker is used to calculate Fibonacci numbers.

The JavaScript lawmaking

The following JavaScript code is stored in the "fibonacci.js" file referenced by the HTML in the adjacent section.

                  self.                    onmessage                    =                    office                    (                    due east                    )                    {                    permit                    userNum                    =                    Number                    (due east.data)                    ;                    fibonacci                    (userNum)                    ;                    }                    function                    fibonacci                    (                    num                    )                    {                    permit                    a                    =                    1                    ,                    b                    =                    0                    ,                    temp;                    while                    (num                    >=                    0                    )                    {                    temp                    =                    a;                    a                    =                    a                    +                    b;                    b                    =                    temp;                    num--                    ;                    }                    cocky.                    postMessage                    (b)                    ;                    }                                  

The worker sets the property onmessage to a function which will receive messages sent when the worker object's postMessage() is called (note that this differs from defining a global variable of that name, or defining a function with that proper noun. var onmessage and function onmessage will define global properties with those names, but they will non register the office to receive messages sent by the spider web page that created the worker). This starts the recursion, spawning new copies of itself to handle each iteration of the calculation.

The HTML code

                                                            <!                      DOCTYPE                      html                      >                                                                                      <html                      >                                                                                      <head                      >                                                                                      <meta                      charset                                              =                        "UTF-8"                                            />                                                                                      <title                      >                    Fibonacci number generator                                              </title                      >                                                                                      <style                      >                                                                                      trunk                        {                        width                        :                        500px;                        }                        div, p                        {                        margin-bottom                        :                        20px;                        }                                                                                                            </style                      >                                                                                      </head                      >                                                                                      <body                      >                                                                                      <grade                      >                                                                                      <div                      >                                                                                      <characterization                      for                                              =                        "number"                                            >                    Enter a number that is an alphabetize position in the fibonacci sequence to run across what number is in that position (east.thousand. enter 5 and you'll get a effect of 8 — fibonacci index position five is 8).                                              </label                      >                                                                                      <input                      blazon                                              =                        "number"                                            id                                              =                        "number"                                            >                                                                                      </div                      >                                                                                      <div                      >                                                                                      <input                      type                                              =                        "submit"                                            >                                                                                      </div                      >                                                                                      </form                      >                                                                                      <p                      id                                              =                        "result"                                            >                                                                                      </p                      >                                                                                      <script                      linguistic communication                                              =                        "javascript"                                            >                                                                                      var                        form                        =                        document.                        querySelector                        (                        'form'                        )                        ;                        var                        input                        =                        document.                        querySelector                        (                        'input[type="number"]'                        )                        ;                        var                        result                        =                        certificate.                        querySelector                        (                        'p#outcome'                        )                        ;                        var                        worker                        =                        new                        Worker                        (                        'fibonacci.js'                        )                        ;                        worker.                        onmessage                        =                        function                        (                        result                        )                        {                        result.textContent                        =                        upshot.data;                        panel.                        log                        (                        'Got: '                        +                        upshot.data                        +                        '\n'                        )                        ;                        }                        ;                        worker.                        onerror                        =                        role                        (                        error                        )                        {                        console.                        log                        (                        'Worker error: '                        +                        mistake.message                        +                        '\north'                        )                        ;                        throw                        error;                        }                        ;                        course.                        onsubmit                        =                        office                        (                        e                        )                        {                        e.                        preventDefault                        (                        )                        ;                        worker.                        postMessage                        (input.value)                        ;                        input.value                        =                        ''                        ;                        }                                                                                                            </script                      >                                                                                      </trunk                      >                                                                                      </html                      >                                                      

The web page creates a div element with the ID result , which gets used to display the result, so spawns the worker. Later on spawning the worker, the onmessage handler is configured to display the results by setting the contents of the div element, and the onerror handler is set to log the mistake message to the devtools panel.

Finally, a message is sent to the worker to offset it.

Attempt this case alive.

Dividing tasks amid multiple workers

As multi-core computers become increasingly common, it'southward often useful to separate computationally circuitous tasks among multiple workers, which may then perform those tasks on multiple-processor cores.

Other types of worker

In addition to defended and shared web workers, there are other types of worker available:

  • ServiceWorkers substantially deed as proxy servers that sit between web applications, and the browser and network (when available). They are intended to (amid other things) enable the cosmos of effective offline experiences, intercepting network requests and taking appropriate action based on whether the network is available and updated assets reside on the server. They will also permit access to push notifications and groundwork sync APIs.
  • Audio Worklet provide the ability for direct scripted sound processing to be done in a worklet (a lightweight version of worker) context.

Debugging worker threads

Well-nigh browsers support debugging of worker threads in their JavaScript debuggers in exactly the same way as debugging the main thread! For example, both Firefox and Chrome list JavaScript source files for both the main thread and active worker threads, and all of these files tin can be opened to set breakpoints and logpoints.

The screenshot below shows this on Firefox. The sources list shows worker.js running in a separate worker thread. When selected this file is opened in the source pane, only like code running in the main thread.

Annotation: Worker scripts are loaded when needed, and hence may not be present in the sources list when a page is commencement loaded.

In the source pane you tin can set up a breakpoint (or logpoint) in a worker thread in the normal way. When execution is paused, the context of the debugger is updated to show correct breakpoints, inline variable preview, call stack, etc., just as y'all'd expect.

Functions and interfaces available in workers

You can utilize most standard JavaScript features inside a web worker, including:

  • Navigator
  • XMLHttpRequest
  • Array, Date, Math, and String
  • setTimeout() and setInterval()

The master thing yous tin can't do in a Worker is directly affect the parent page. This includes manipulating the DOM and using that page's objects. Yous have to exercise it indirectly, by sending a message back to the main script via DedicatedWorkerGlobalScope.postMessage, then actioning the changes from there.

Note: You can test whether a method is available to workers using the site: https://worker-playground.glitch.me/ . For example, if you enter EventSource into the site on Firefox 84 you'll see that this is not supported in service workers, only is in defended and shared workers.

Specifications

Meet too

campbellaunuentid.blogspot.com

Source: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers

Postar um comentário for "Run a Script Agains a Web Page"