proto-n
proto-n

Reputation: 625

Best way to wait for a chrome.tabs.query callback?

I'm writing a Chrome extension for my own use. I'm querying the current tab's index from an injected script like this:

[injected script]

chrome.runtime.sendMessage({whatIsMyIndex:1}, function(response){
   var myIndex = response.index;
});

[background script]

chrome.runtime.onMessage.addListener(
   function(request, sender, sendResponse) {
      if (request.whatIsMyIndex){
         sendResponse({index: sender.tab.index});
      }
   }
);

Now this is all good and fine, but then I need to return the url of the first tab as well:

[injected script 2]

chrome.runtime.sendMessage({whatIsMyIndex:1}, function(response){
   var myIndex = response.index;
   var url = response.url;
});

[background script 2]

var url;

//this uses sendResponse when the requested values arrive
function respond(sendResponse, index){
   if(typeof(url)!="undefined"){
      sendResponse({index:index, url:url});
   } else {
      setTimeout(respond, 15, sendResponse, index);
   }
}

chrome.runtime.onMessage.addListener(
   function(request, sender, sendResponse) {
      if (request.whatIsMyIndex){
         chrome.tabs.query({index:0, currentWindow:true}, function(tabs){
            url=tabs[0].url;
         }
         setTimeout(respond, 15, sendResponse, sender.tab.index);
         return true; //so i can use sendResponse later
      }
   }
);

Now, this code works just fine. My question is, is there any way to accomplish this without the need for setTimeout? Adding a fixed 15ms delay doesn't seem right.

If only I could get chrome.tabs.query's callback to take my sendResponse() as a parameter...

(Storing sendResponse() in a global variable is not possible, since there will be ~20 tabs doing this at the same time, and all of them need their own responses.)

I don't need any working (or not working) code here, only some ideas/guidelines.

Upvotes: 1

Views: 4213

Answers (1)

rsanchez
rsanchez

Reputation: 14657

Just call sendResponse inside the chrome.tabs.query callback, instead of setting the variables:

chrome.runtime.onMessage.addListener(
   function(request, sender, sendResponse) {
      if (request.whatIsMyIndex){
         chrome.tabs.query({index:0, currentWindow:true}, function(tabs){
            sendResponse({index:sender.tab.index, url:tabs[0].url});
         });
         return true; //so i can use sendResponse later
      }
   }
);

Each invocation of the onMessage callback function creates a new closure, so the sendResponse inside the tabs.query callback function will be bound to the right function.

Upvotes: 8

Related Questions