1

Am working on a chrome plugin, and need to sendMessage from an 'app page' to a 'content script' and then get the return messages, from inside a loop. But since the loop doesn't wait for the sendMessage to return a value before starting on the next iteration, it is screwing up the return values. Here is a sample of what the code looks like:

for (i=0; i<data[i2].data.length; i++)
    {
    console.log("SENDING: i=" + i + "; i2=" + i2);

    // Send message to content script with the query value
    chrome.tabs.sendMessage(tabid, {x: 'val-x', y: data[i2].data[i].val-y}, function(response) {

        console.log("RECEIVING: i=" + i + "; i2=" + i2);
        console.log("RECEIVING: val1=" + response.value1+ "; val2=" + response.value2);


        // ANOTHER FUNCTION CALL
        dothis(response.value1, response.value2, response.value3);

    });

What can I do to make it all work synchronously?

Here is an overview of what am doing on the content-script:

function function1(x) {/* some code ... */}
function function2(y) {/* some code ... */}

// EventListener to listen to messages sent from app
chrome.runtime.onMessage.addListener(
function(sent, sender, sendResponse) {

  // some code here //

      val1 = function1(sent.x);
      val2 = function2(sent.y);

  }

  sendResponse({value1: val1, value2: val2});

  });

So, in loop1 these functions get called. Then, they called again by loop2 before they have a chance to return the values back.

Mike Hall
  • 11
  • 4
  • Could you clarify what you are referring to by "loop2"? Try as I might, I see one original loop in the top sample, but I don't see another...? – David W Jun 22 '15 at 15:20
  • And could you possibly offer some sample data that illustrates how the data is being incorrectly affected? – David W Jun 22 '15 at 15:24
  • @DavidW I just meant the 2nd iteration. not another loop. Here is how the data is getting affected: iteration1 sends a message (with some parameters) to the content-script. The content script on getting this message, passes them on to function1 & 2. But while these two functions are still in process, iteration2 (from app page) starts & calls these functions again with new values. So I get empty values back for 1st iteration, and get values back only for 2nd iteration (i.e the last iteration, since it's set to loops only twice right now) – Mike Hall Jun 22 '15 at 15:29
  • Hmmm...is there any way you could make function1 and function2 part of a closure that is called from your callback, just before you use the results? I *think* that would defer execution the way you need.. – David W Jun 22 '15 at 15:38
  • I came across another post where someone was having trouble with async chrome tab message processing and used closures. May or may not be helpful, so take a look: http://stackoverflow.com/questions/14094447/chrome-extension-dealing-with-asynchronous-sendmessage – David W Jun 22 '15 at 16:44
  • @DavidW thanks. hv bookmarked it.. – Mike Hall Jun 22 '15 at 19:12
  • Is there a reason you're not sending everything at once: `chrome.tabs.sendMessage(tabid, data[i2].data, responseFunction)`? – Teepeemm Jun 22 '15 at 21:54
  • @Teepeemm I didn't get you. I am sending it all at once.. – Mike Hall Jun 23 '15 at 18:26
  • No, you're sending it each time through the loop: `for (i=0; i – Teepeemm Jun 23 '15 at 19:59
  • @Teepeemm yeah, I guess I could. Such a simple sol. Thanks :) I thought about it, and I think it'll not be easy for me to have it loop there. coz for some of it I need to load a different URL into the tab before I can get the data (haven't coded for tht part yet). It still can be done, but its slightly more simple, easier to read as a prog and organized if it stays here imo.. – Mike Hall Jun 24 '15 at 16:31

1 Answers1

1

One option would be to make your function(response) recursive. When it runs, call this same method again. Pass in some of your "looping" variables, and just do an if check at the beginning.

function AnotherGoRound(i,data) {
    if (i<data[i2].data.length) {
        console.log("SENDING: i=" + i + "; i2=" + i2);

        // Send message to content script with the query value
        chrome.tabs.sendMessage(tabid, {x: 'val-x', y: data[i2].data[i].val-y}, function(response) {

            console.log("RECEIVING: i=" + i + "; i2=" + i2);
            console.log("RECEIVING: val1=" + response.value1+ "; val2=" + response.value2);


            // ANOTHER FUNCTION CALL
            dothis(response.value1, response.value2, response.value3);
            AnotherGoRound(i + 1, data);
        });
    }
}
AnotherGoRound(0, data);
rsanchez
  • 14,467
  • 1
  • 35
  • 46
Coding Orange
  • 548
  • 4
  • 7
  • Nope, doesn't work very well :( I checked my console logs, and the SENDING: i=0 and SENDING: i=1 get logged before I get the return values for i=0 (i.e a log of SENDING: i=1 before RECEIVING: i=0).. So basically it means, iteration1, it sends the values, doesn't wait for it to return the values before going on iteration2. (Although the script is working now, coz it seems to delay things enough for me to get the data back from both iterations, but the problem still hasn't been solved). – Mike Hall Jun 22 '15 at 16:03
  • this will work but its not optimal if you want to take advantage of synchronous messages. there are ways to make it faster. – Zig Mandel Jun 22 '15 at 16:51
  • @MikeHall the only way that could happen with this code is if you call `AnotherGoRound` more than once. You should only call it once, with `AnotherGoRound(0, data)` – rsanchez Jun 22 '15 at 16:51
  • @rsanchez you are right. I did call it twice, coz I had to declare it outside. I don't understand how I can declare a function directly like this without the 'function' keyword inside another function. I tried the above, and it gives an ' unexpected { ' error.. I also tried doing var functionholder = functionAnotherGoRound(i) {}.. but get the same error. can you please tell me exactly how I can achieve this? – Mike Hall Jun 22 '15 at 18:36
  • @MikeHall I edited the answer. You first declare your function with the `function` keyword and after that you call it. – rsanchez Jun 22 '15 at 18:42