Receiving message response in extension action does not handle promise

1,288 views
Skip to first unread message

Samuel Wadrose

unread,
Aug 24, 2023, 9:53:02 AM8/24/23
to Chromium Extensions
I can't seem to find any information on how an action script should handle message passing. When within the action, I am sending a message to the service-worker which then awaits an async function to the send response of the returned value. The script in the action does not wait on the response. If I respond with a static value from the service-worker, the action script does receive it.

To replicate:
(1)
In script for action popup you'll need:

const userName = await chrome.runtime.sendMessage({action: 'getUserName'})
console.log(userName)

(2) In service worker you'll need a message listener that contains:

if (request.action === 'getUserName') {
//getUserName() is getting the username from an external database (could use getting from storage.local)
const userName = await getUserName();
sendResponse(userName)

What is the expected result?
userName in action popup script should await the response and be resolved to the proper value

What happens instead?
userName is immediately set to undefined. The action popup script does not wait on the response

Why is this happening? Thank you for any help!

Patrick Kettner

unread,
Aug 24, 2023, 9:59:34 AM8/24/23
to Samuel Wadrose, Chromium Extensions
Hey Sam!
In order for a caller to get the message back from an async response directly (rather than using the third argument  - sendResponse), the function needs to return `true`. The literal true, not just a truthy thing. As you are using async/await, is it possible you are in an async function, which would mean you are returning a promise, rather than `true`?



--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/e4e07b41-6290-4159-bc64-027b10baad65n%40chromium.org.

Oliver Dunk

unread,
Aug 24, 2023, 10:00:32 AM8/24/23
to Samuel Wadrose, Chromium Extensions
Hi Samuel,

Repeating some of what Patrick said because I already had a draft!

It sounds like you're probably not returning true from your onMessage listener, which can easily happen if you're using an async function - since that will sneakily change the return to a promise without you realising.

If you try the following, it should work:

```
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {

  if (request.action === 'getUserName') {
    getUserName().then(sendResponse);
  }
  return true;
});
```

Here's a quick demo of an extension that works on example.com (link).

There's an open bug for a possible solution to this here: https://bugs.chromium.org/p/chromium/issues/detail?id=1185241

Hope that helps!
Oliver Dunk | DevRel, Chrome Extensions | https://developer.chrome.com/ | London, GB


--

Samuel Wadrose

unread,
Aug 24, 2023, 10:31:57 AM8/24/23
to Chromium Extensions, Oliver Dunk, Chromium Extensions, Samuel Wadrose
Thank you for you help. That solution works for my case. 

Do you mind explaining why this setup would not work?

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

if (request.action === 'getUserName') {
const user = await getUserName();

sendResponse(user);
}
//Is this return true still needed?
return true;
  });

Oliver Dunk

unread,
Aug 24, 2023, 10:36:06 AM8/24/23
to Samuel Wadrose, Chromium Extensions
Yay!

The return true is needed to tell Chrome that you're not going to reply right away. Without it, as soon as the synchronous part of your code is complete, Chrome assumes you are not going to respond and closes the connection between your content script and background.

The subtle issue in the code you shared is that you're using an async function. So while you think you're returning true, behind the scenes you actually have a function that returns a promise. The extension APIs don't support this.

Hopefully that makes sense? There's some additional detail here if it helps: https://javascript.info/async-await

Oliver Dunk | DevRel, Chrome Extensions | https://developer.chrome.com/ | London, GB

Samuel Wadrose

unread,
Aug 24, 2023, 10:43:30 AM8/24/23
to Chromium Extensions, Oliver Dunk, Chromium Extensions, Samuel Wadrose
That makes sense and is the answer I was looking for.  Thank you for clearing that up!
Reply all
Reply to author
Forward
0 new messages