Hugo Buff
Hugo Buff

Reputation: 421

Passing jQuery reference through Web Worker

I'm working on offloading some url polling requests to a web worker. To do this, I need to fetch certain attributes from the DOM element of invokation, pass them into a url request, then update the original DOM element with the results. Since multiple DOM elements use this function to fetch updates, I need to pass through $(this) or an equivalent unique identifier to ensure the correct element is updated.

I understand from questions such as "Passing objects to a web worker" and "Can I pass a jQuery object to a web worker" that this is not possible, so I am looking for a means to emulate this.

Here is a rough outline of my code:

//main.js
function update(){
    var data = { 'id'     : $(this).attr('itemid'),
                 'filter' : $(this).attr('filter')}
    updatePoller.postMessage(data);
}

//worker.js
this.onmessage = function(e){
    //format params from e.data
    //make GET request to url
    //when done...
    postMessage(req.responseText);
}

//main.js (again)
updatePoller.onmessage = function(message){
    //process response
    //update child elements of $(this)
}

As you can see, I don't need to access $(this) inside the web worker, but I need the reference once the request has returned in order to update the correct element. Are there any ways to pass a unique reference to a DOM element through a web worker?

Upvotes: 1

Views: 329

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074168

The usual way to uniquely identify an element when you can't use its reference is to use an id. Alternately, you could use a data-* attribute, but really ids were made for this specific purpose.

So (see comments):

//main.js
var lastId = 0;
function update(){
    // Assign ID if necessary
    if (!this.id) {
        ++lastId;
        this.id = "__auto" + lastId;
    }
    var data = { 'id'       : $(this).attr('itemid'),
                 'filter'   : $(this).attr('filter'),
                 'elementId': this.id}
    updatePoller.postMessage(data);
}

//main.js (again)
updatePoller.onmessage = function(message){
    // Use the `element` value sent back to look it up by ID:
    $("#" + message.data.elementId).xyz();
}

If having all of those automatic globals (since id values create automatic globals) bothers you, you could remove the ID when done with it:

//main.js (again)
updatePoller.onmessage = function(message){
    var elm = $("#" + message.data.elementId);
    if (elm.attr("id").startsWith("__auto")) {  // auto ID?
        elm.attr("id", "");                     // remove it
    }
    elm.xyz();
}

or with less jQuery:

//main.js (again)
updatePoller.onmessage = function(message){
    var elm = $("#" + message.data.elementId)[0];
    if (elm && elm.id.startsWith("__auto")) {
        elm.id = "";
    }
    $(elm).xyz();
}

Upvotes: 2

Related Questions