2

Forgive me if ever an answer has already been given, I've been searching for more than 1 hour but didn't find a way to fix my problem.

So here is my problem :

I am coding a chrome extension and have 2 JS scripts, "script.js" and "background.js". In my script.js, I am using chrome.runtime.sendMessage to message my background script.

Withing my background script, I made a listener to receive the message and download several images from links provided via the message, Which means the function may take up to 1 minute before the download to be finished. (By the way, I am using promise, then I know my code is executed step by step)

script.js

chrome.runtime.sendMessage({message: "download", parameters: images}, function (response) {
    console.log(response);
});

background.js

chrome.runtime.onMessage.addListener(function (arg, sender, sendResponse) {
    doSomeLongStuff().then(function () {
        sendResponse(myResponse);
        return true;
    })
});

And in my script, I am unable to receive my answer. Even if I add a setInterval to the responseCallback, the response will always be undefined

If ever someone could tell me if there is a way to tell the responseCallback to wait for a long answer, any help would be appreciated.

Rémi Bosgaerd
  • 150
  • 1
  • 12
  • Possible duplicate of [Chrome Extension Message passing: response not sent](https://stackoverflow.com/questions/20077487/chrome-extension-message-passing-response-not-sent) – wOxxOm Jan 30 '19 at 14:31

4 Answers4

0

This is a common problem, i.e. returning a response from an asynchronous operation. Chrome will ignore any call to sendResponse() if it's not done synchronously.

The solution is not to think in terms of sending a response, but sending a subsequent message in its own right.

chrome.runtime.onMessage.addListener(function (arg, sender, sendResponse) {
    doSomeLongStuff().then(function () {
        //don't call sendResponse() here, send a separate message to script.js
        return true;
    })
});

You send this via chrome.tabs.sendMessage in the callback to a request to chrome.tabs.query. Docs.

Mitya
  • 33,629
  • 9
  • 60
  • 107
  • Thank you, this is exactly the kind of help I was looking for Plus : we can access ```tab.id``` from the ```sender``` param of the listener. – Rémi Bosgaerd Jan 30 '19 at 14:22
  • 2
    The code in the question (and this answer as well) is wrong: `return true;` should be outside of the async sub-function call as the idea is to return true from the listener to tell the API that invoked the listener to wait. When put in the right place, it enables sendResponse inside an asynchronous call, no need to send another message. – wOxxOm Jan 30 '19 at 14:42
  • @wOxxOm completely didn't notice the return - obviously wrong. – Mitya Jan 30 '19 at 15:29
0

This works for me:

background.js

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
      let send = sendResponse;
      doSomeLongStuff().then(response =>{
           send(response);
      });
      return true;
});

And in Firefox (the same, just using the browser namespace):

browser.runtime.onMessage.addListener(function (request, sender, sendResponse) {
      let send = sendResponse;
      doSomeLongStuff().then(response =>{
           send(response);
      });
      return true;
});
Petr L.
  • 414
  • 5
  • 13
0

your main mistake that you return true in "then" callback, but you must return true in chrome.runtime.onMessage.addListener calback. It will be work:

background.js

chrome.runtime.onMessage.addListener(function (arg, sender, sendResponse) {
    doSomeLongStuff().then(function () {
        sendResponse(myResponse);
    });

    return true;// correct place of return true
});
Petr Moroz
  • 111
  • 1
  • 3
-1

SOLUTION :

Utkanos brought the right answer, so if someone is looking for the same answer here is how it is working now :

script.js

chrome.runtime.sendMessage({message: "download", "parameters": images});
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    console.log(request);
});

background.js

chrome.runtime.onMessage.addListener(function (arg, sender, sendResponse) {
    doSomeLongStuff().then(function () {
        chrome.tabs.sendMessage(sender.tab.id, {'status': 'finished'});
    })
});
Rémi Bosgaerd
  • 150
  • 1
  • 12
  • The other answer showed `return true` in the wrong place so you can simplify the code: there's no need to send another message. Make sure to always check the documentation. – wOxxOm Jan 30 '19 at 14:32