0

This is in a background script. Everything seems to work down to the result, but my list variable seems to be empty no matter where I declare it in the scope. How do I use sendResponse to get the data back to my content script? What am I missing?

chrome.runtime.onMessage.addListener(
  function (request, sender, sendResponse) {

    list = [];
    // list available channels
    if (request.action.includes("channels")) {

      function inContent() {
        let elems = document.getElementsByClassName("name-sec");
        let channelsList = [];
        for (let ii = 0; ii < elems.length; ii++) {
          let channel = elems[ii];
          channelsList.push(channel.innerText);
        }
        return channelsList;
      }

      chrome.tabs.executeScript({ code: `(${inContent})()` }, function (result) {
        list = result[0];
      });

      // list is empty
      sendResponse({action: `Channels List:${"\n"}${list.join("\n")}`})
    }
  }
);

1 Answers1

0

chrome API executes its callbacks asynchronously. Using an asynchronously-invoked callback doesn't run it immediately, it's similar to registering a one-time listener for the 'load' event and then the next statement starts running (calling sendResponse in your case) and uses the current value of list i.e. [].

The solution is two-fold:

  1. wait for the asynchronous callback;
  2. tell onMessage to keep the channel open.
if (...) {
  chrome.tabs.executeScript({ code: `(${inContent})()` }, function (result) {
    list = result[0];
    sendResponse({action: `Channels List:${"\n"}${list.join("\n")}`});
  });
  return true;
}
wOxxOm
  • 65,848
  • 11
  • 132
  • 136