Kyle Hu
Kyle Hu

Reputation: 121

How to avoid "The message port closed before a response was received" error when using await in the listener

I am writing a chrome extension with node module "chrome-extension-async" and meeting a problem when use await in the listener of background.

The content.js which will be injected into the page will send a message to the background, asking it to do some IO operations which is async:

// content.js
const package = await chrome.runtime.sendMessage({param: ...})
console.log(package)

// background.js
chrome.runtime.onMessage.addListener(async (request, sender, 
sendResponse) => {
    const value  = await doIOOperation();
    sendResponse(value);
})

However, chrome will report errors like below:

Uncaught (in promise) Error: The message port closed before a response was received.

I think there must be some conflict when using async/await in the listener, Anyone know how to solve this problem?

Upvotes: 10

Views: 25393

Answers (2)

bob
bob

Reputation: 7985

To expand on all the notes and clarify @RomanistHere's answer:

// a couple example async example functions
var greet;
const whatever = async function(){
    greet = "hello";
}
const getSomething = async function(){
    return "bob";
}

// set up a function outside the callback, 
// ... giving freedom to leverage async/await.
const asyncFunctionWithAwait = async (request, sender, sendResponse) => {
    
    // now we can do await's normally here
    await whatever();
    let name = await getSomething();
    
    // since our response function is carried through "by reference",
    // therefore we can call it as if it were within the listener callback.
    sendResponse(greet + name)

}

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

    // exec in the body of this callback,
    // ... passing original function through.
    asyncFunctionWithAwait(request, sender, sendResponse)

    // per:
    // http://developer.chrome.com/extensions/runtime.html#event-onMessage
    //
    // This function becomes invalid when the event listener returns, 
    // unless you return true from the event listener to indicate you 
    // wish to send a response asynchronously (this will keep the message 
    // channel open to the other end until sendResponse (3rd arg) is called).
    return true;

});

Upvotes: 5

RomanistHere
RomanistHere

Reputation: 892

const asyncFunctionWithAwait = async (request, sender, sendResponse) => {...}

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

    return true
})

worked for me

Upvotes: 11

Related Questions