0

I am trying to request some data from one script to another. The script that has the data has this listener with my guess at returning that data:

chrome.runtime.onMessage.addListener(function(message,sender) {   
  if (message.msg=="start") {
     start();
  }
  else if (message.msg=="stop") {
     stop();
  }
  else if (message.msg=="sendData") {
     sendResponse(data);
  else {
     configure();
  }
});

What I don't understand is how to recover that data in the requesting script. Do I need a listener in the requesting script or is the data returned as part of the request thus?

data=await chrome.runtime.sendMessage({msg:"sendData"});

TIA.

Using Joe's suggestion, modified for async operation, here is my code:

In the requesting background script:

 chrome.runtime.sendMessage({msg:"sendData"},await function(response) {
     console.log(response.data);
 });

In the request processing script:

chrome.runtime.onMessage.addListener(async function(message,sender,sendResponse) {   
   if (message.msg=="start") {
      start();
  }
  else if (message.msg=="stop") {
      stop();
  }
  else if (message.msg=="sendData") {
      var data_obj=await requests(base_url+"/projects.json");
       console.log(data_obj);
       sendResponse({"data":data_obj.results});
  }
  else {
       configure();
  }
});

The sendResponse seems to wait for the requests call to return. However, the response function does not wait. So the problem now is how to get the response function to wait until the requester sends the data.

Updated again per Joe's suggestion. This is how I interpreted your code. Requesting script:

chrome.runtime.sendMessage({msg:"sendData"},function(response) {
    const data=response.data;
    console.log(data);
});

Processing script

chrome.runtime.onMessage.addListener(async function(message,sender,sendResponse) {   
   if (message.msg=="start") {
      start();
   }
   else if (message.msg=="stop") {
       stop();
   }
   else if (message.msg=="sendData") {
       requests(base_url+"/projects.json").then(data=>data.json()).then(result => {
           sendResponse({"data":result});
       });
       return(true);
   }
   else {
       configure();
   }
});

Unfortunately I get this error on "const data=response.data":

Error handling response: TypeError: Cannot read properties of undefined (reading 'data') at chrome-extension://fplbgdfknpplbjbggkkhnpnifgfeojpo/config_mgmt.js:87:24

Wt Riker
  • 514
  • 12
  • 24
  • The posted code can certainly work, depending on how you get the data, so what's the problem? Did you debug the code? See also [How to see background devtools](/a/10258029) and note that the popup is a separate devtools. – wOxxOm Sep 30 '22 at 18:26
  • Please see [ask], then revise your post title to ask a clear, specific question. – isherwood Sep 30 '22 at 18:31

2 Answers2

1

Your question is fairly vague, but I am assuming you want to collect data from background.js from a content script?

If the data is static and can be accessed without an async function, then you would do something like this:

// content_script.js
chrome.runtime.sendMessage({
    'message': 'get-data'
}, function (response) {
    const data = response.data
    console.log(data) // ['example data in array']
})


// background.js
const data = ['example data in array']

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    if (request.message == 'get-data') {
        sendResponse({
            'data': data
        })
    }
})
Jridyard
  • 761
  • 3
  • 9
  • I have updated the OP using your suggestion but I do need to use async/await. – Wt Riker Oct 01 '22 at 15:52
  • Alright gotcha, ill share a code snippet to manage async with the example being to use fetch. the trick is to return true to keep the message port open. DONT use await, just make your fetch/async request without await and in the .then() return you will send the response data to your extension – Jridyard Oct 02 '22 at 04:08
0

For async requests, dont use await, return true to keep the port open, and send the reponse in the .then() return section.

// content_script.js
chrome.runtime.sendMessage({
    'message': 'get-data'
}, function (response) {
    const data = response.data
    console.log(data) // this will log whatever data you fetched
})


// background.js
// Dont use async function, leave it as a function or else the message port will not stay open for you to send the response
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    if (request.message == 'get-data') {
        const url = 'https://www.exampleurl.com/'
        fetch(url).then(data => data.json()).then(result => {
            sendResponse({
                'data': result
            })
        })
        return true // you need to add the return true to keep the message port open, dont worry though the response will contain your data
    }
})
Jridyard
  • 761
  • 3
  • 9
  • Thanks again for the help but I still have something wrong. I've updated the OP with how I think I interpreted you code. – Wt Riker Oct 02 '22 at 15:30
  • Got it. It's not working because your background.js message contains "async function" - as I mentioned in my reponse, you have to have it stay like this ```chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {``` -- you cant sendResponse for async messages, instead you are returning true to keep the message port open and sending the response from inside the fetch return. Everything should be right, just remove "async" from your listener – Jridyard Oct 02 '22 at 16:40
  • 1
    Also, just a thought - you could probably do the fetch request from content.js and cut out the message passing. You should avoid using this method as much as possible – Jridyard Oct 02 '22 at 16:44
  • I didn't know that. I can reproduce the fetch code but I thought it was more efficient to reuse the code. – Wt Riker Oct 03 '22 at 14:22