React Chrome Extension - Problems with service worker communication

1,257 views
Skip to first unread message

Stefan Strathmeier

unread,
Feb 9, 2021, 4:18:31 AM2/9/21
to Chromium Extensions
Hi guys,

I just started to work on my first React Chrome Extension and I am already running into problems using a service worker. It seems like my code can't communicate with my service worker. What would be the best way to show you my code? I am quite new to programming and don't know my way around.

Thanks for the help! :)

Best wishes

Stefan

Stefan Strathmeier

unread,
Feb 9, 2021, 6:10:49 AM2/9/21
to Chromium Extensions, Stefan Strathmeier
Ah, one of my colleagues gave me a hint to use Github gists to show you the code. :-) Here we go:

Stefan Strathmeier

unread,
Feb 9, 2021, 9:38:19 AM2/9/21
to Chromium Extensions, Stefan Strathmeier

Sorry, I totally forgot to add my problem with the code. I always see the following error message in the console of the extension.

TypeError: (e.adapter || i.adapter) is not a function
    at background.js:1

I guess it could have something to do with the axios import in the background.js?

Thank you so much! :-)

Stefan

wOxxOm

unread,
Feb 9, 2021, 9:58:38 AM2/9/21
to Chromium Extensions, stefanst...@gmail.com
Remove register-sw.js and its usage.
Extensions register their background service worker automatically when you declare it using "background" key in manifest.json

Rework your code to get the response directly via messaging:

const addTitleToWatchlist = () => {
  return new Promise(resolve => {
    chrome.runtime.sendMessage({ type: "ADD_TO_WATCHLIST" }, resolve);
  });
};

Remove async from onMessage listener declaration. Extensions in Chrome can't return a Promise yet and it's unclear if Chromium team will implement it properly or they will keep the old nonsensical method explained below.

  • To do something asynchronously in onMessage you should use a separate Promise (or function) and return true from the listener. The listener itself can't be async because this keyword makes the function return a Promise.
  • Use sendResponse as shown in the documentation instead of using storage.
  • Remove chrome.tabs.query and use sender parameter of the listener because the tab that sent the message may be inactive.
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === "ADD_TO_WATCHLIST") {
    addToWatchList(message, sender).then(sendResponse);
    return true; // this will keep the internal messaging port open
  }
});

async function addToWatchList(message, sender) {
  const articleId = getArticleId(sender.url);
  const requestedArticle = await getArticleInfos(articleId);
  return prepareMessage(requestedArticle, articleId);
}

wOxxOm

unread,
Feb 9, 2021, 10:22:50 AM2/9/21
to Chromium Extensions, wOxxOm, stefanst...@gmail.com
Correction: you'll need to keep using chrome.tabs.query if you send the message from a popup because sender.url will have be the chrome-extension:// URL of the popup page itself, not of the tab.

Stefan Strathmeier

unread,
Feb 14, 2021, 1:44:59 AM2/14/21
to Chromium Extensions, wOxxOm, Stefan Strathmeier
Hi wOxxOm! Thank you so much for your reply and the help! :-) And sorry, that I didn't find the time to answer much earlier. Our second son was just born.

I am still having problems with Promises (and async/await in fact). What is happening in your code? Is the resolve function that gets called in addTitleToWatchlist the returned function of the async addToWatchList?

And the async keyword is only not allowed in the Chrome APIs, right? :-)

Thank you so much

Stefan

wOxxOm

unread,
Feb 14, 2021, 1:57:52 AM2/14/21
to Chromium Extensions, stefanst...@gmail.com, wOxxOm
>   I am still having problems with Promises (and async/await in fact). What is happening in your code? Is the resolve function that gets called in addTitleToWatchlist the returned function of the async addToWatchList?

This is the standard method of promisifying a callback-based call. Note that addTitleToWatchlist is not async, let this term be reserved for the keyword async. The function, just like its child call to chrome.runtime.sendMessage, are simply asynchronous. When you declare a function using the async keyword, it causes the function return a Promise internally. This should be covered in tutorials but I don't have any link so try googling if you want more info.

> And the async keyword is only not allowed in the Chrome APIs, right? :-)

That's not what I meant. You can use async and Promise anywhere but callbacks/events of extension's chrome API don't recognize a Promise as a result so it will be simply ignored usually, except for cases like onMessage where the listener must return a literal value, not a Promise, so returning a Promise will break the functionality.

Simeon Vincent

unread,
Feb 16, 2021, 9:07:03 PM2/16/21
to Chromium Extensions, wOxxOm, stefanst...@gmail.com
Stefan, for a little more background on asynchronicity in JavaScript, I wrote up a comparison of several different approaches to asynchronisity that you might find useful. https://stackoverflow.com/questions/57892623/how-do-i-make-my-code-asynchronous-google-chrome-extension/57895216#57895216

Cheers,

Simeon - @dotproto
Chrome Extensions DevRel

Stefan Strathmeier

unread,
Feb 20, 2021, 3:43:21 PM2/20/21
to Chromium Extensions, Simeon Vincent, wOxxOm, Stefan Strathmeier
Hi wOxxOm, hi Simeon,

thank you so much for your help! I will have another look at my code and I will check out the link. :-)

Best wishes from Germany

Stefan
Reply all
Reply to author
Forward
0 new messages