0

I am using Web Workers for the first time, and need some help making my function work.

Here is my code:

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

...

for(i = 0; i < passaggi.length; i++) {
     lat = passaggi[i].lat;
     lon = passaggi[i].lon;
     timestamp = passaggi[i].timestamp;



     myWorker.postMessage([lat, lon]);
     myWorker.onmessage = function(e) {

         console.log('Message received from worker');
         nome = e.data
         tmp = "<table border='1'><tr><td>" + i + "</td><td>" + nome + "</td><td>" + timestamp + "</td></tr></table>";
         tabella.innerHTML += tmp;


     }
}

Passaggi is an array; I want the worker to parse 'lat' and 'lon' of each item of the array using the Google Geocoding API, return the name of the town.

When the main function receives the message, a table is added containing the name and a timestamp. Tabella is the div that will contain it.

Problem is, the function creates the correct number of tables but each contains the data for the last element in passaggi! Output example:

| 4 | Rome | 2015-09-14 23:44:38 |
| 4 | Rome | 2015-09-14 23:44:38 |
| 4 | Rome | 2015-09-14 23:44:38 |
| 4 | Rome | 2015-09-14 23:44:38 |

This is the content of worker.js, but the code seems to be fine:

onmessage = function(data){

        var mapAPI = "http://maps.googleapis.com/maps/api/geocode/json?latlng=" + data.data[0] + "," + data.data[1] + "&sensor=true";


        var req = new XMLHttpRequest();
        req.open('GET', mapAPI, true);
        req.onreadystatechange = function (aEvt) {
            if (req.readyState == 4){
                if(req.status == 200){
                    result = JSON.parse(req.responseText);
                    console.log(result);
                    message = result.results[0].address_components[2].long_name;
                    postMessage(message);
                }
            else
                console.log("Error loading page\n");

            }
        }
    req.send(null);
}

As I understand, Web Workers are useful for executing functions in background without blocking the rest of the page; parsing coordinates seemed a good application, for that. What am I doing wrong?

Thanks in advance for your help.

Ferduun
  • 137
  • 13
  • Does it help if you declare all your variables properly, so that they are local to their functions and not implicitly global? – Thilo Sep 15 '15 at 00:15
  • Also, you cannot use the loop counter `i` in a callback. By the time the callback is invoked, the loop will have finished, and `i` will be past the last iteration (or something completely different). – Thilo Sep 15 '15 at 00:17

1 Answers1

2

your var i is a reference meaning it will have the Last value of the loop, you should use an IIFE:

(function(i) {
    myWorker.onmessage = function(e) {

     console.log('Message received from worker');
     nome = e.data
     tmp = "<table border='1'><tr><td>" + i + "</td><td>" + nome + "</td><td>" + timestamp + "</td></tr></table>";
     tabella.innerHTML += tmp;


 }})(i);
taxicala
  • 21,408
  • 7
  • 37
  • 66
  • Also need to do that for `timestamp`. – Thilo Sep 15 '15 at 00:19
  • Applied the suggestion for timestamp as well and made proper declarations, the value of i is 3 instead of 4 now but otherwise the same result. Guess that means it now stops at the correct cycle? (i = 3, 4 elements shown) – Ferduun Sep 15 '15 at 00:25