Asynchronous chrome.runtime.sendMessage callback with response of undefined:

According to the docs(opens new window), chrome.runtime.onMessage.addListener does not support async functions. Instead, the listener must return true to indicate asynchronous response. Otherwise, “The message port closed before a response was received” will show up in chrome.runtime.lastError.

To work around this, here is an asynchronous wrapper.

function asyncMessageResponder(asyncFn) {
  return (request, sender, sendResponse) => {
    Promise.resolve(asyncFn(request, sender)).then(
      (result) => sendResponse({ result }),
      (error) => {
        console.error(error)
        sendResponse({ error: { message: error.message } })
      }
    )

    // Indicate that the message will be handled asynchronously.
    return true
  }
}

To use:

chrome.runtime.onMessage.addListener(
  asyncMessageResponder((request, sender, sendResponse) => {
    // ...
  })
)