在侦听器中使用等待时如何避免“收到响应之前关闭消息端口”错误

Kyl*_* Hu 6 google-chrome-extension

我正在编写一个带有节点模块“chrome-extension-async”的 chrome 扩展,并await在后台侦听器中使用时遇到问题。

将被注入页面的 content.js 会向后台发送一条消息,要求它执行一些异步的 IO 操作:

// 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);
})
Run Code Online (Sandbox Code Playgroud)

但是,chrome 会报告如下错误:

未捕获(承诺)错误:消息端口在收到响应之前关闭。

我认为在侦听器中使用 async/await 时肯定会有一些冲突,有人知道如何解决这个问题吗?

Rom*_*ere 6

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

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

    return true
})
Run Code Online (Sandbox Code Playgroud)

为我工作

  • 如果您解释了您提供的代码如何回答问题,这将是一个更好的答案。 (6认同)

bob*_*bob 5

扩展所有注释并澄清@RomanistHere 的答案:

// 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;

});
Run Code Online (Sandbox Code Playgroud)