Chrome 扩展程序消息未发送响应(未定义)

wor*_*ith 8 javascript google-chrome google-chrome-extension

供将来参考:我通过将 onMessage/sendMessage 分别切换到后台脚本和内容脚本来解决这个问题。我不知道为什么这有效,但它确实有效。

在过去的三个小时里,我一直在尝试调试这个问题——我正在构建一个 chrome 扩展,并且我发送的消息的响应一直是“未定义”。我试图获取用户所在选项卡的文本并用它来进行一些分析。

内容脚本:

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        if (request.method == "collectText") {
            sendResponse({data: document.body.innerText, method: "collectText"});
        }
        return true;
    }
);
Run Code Online (Sandbox Code Playgroud)

弹出脚本:

chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
  chrome.tabs.sendMessage(tabs[0].id, {method: "collectText"}, function(response) {
      if (response) {
        txt = response.data;
        console.log("response arrived");
        console.log(txt);
      } else {
        console.log("No response.");
      }
  });
});
Run Code Online (Sandbox Code Playgroud)

console.logs 当前在那里,以便我知道数据是否返回(它不是 - 每次脚本运行时都会记录“无响应”,并且txt最终未定义)。我不确定为什么这不起作用(并且我已经尝试了相同脚本的许多变体但无济于事)。我在扩展程序或我所在页面的控制台中没有收到任何错误。我应该使用后台脚本而不是在 popup.js 中编写所有内容吗?

谢谢你!

小智 17

如果您异步返回答案,则可能会发生此类错误。(尽管这在你给出的例子中不可能发生)

// sender
runtime.sendMessage(msg, response => {
  if (!response)
    console.error("This was a fiasco :", runtime.lastError.message);
});

// receiver
runtime.onMessage.addListener(async (request, sender, sendResponse) => {
  var response = await answer_something(request);
  sendResponse(response);
});

// same problem for this receiver
runtime.onMessage.addListener((request, sender, sendResponse) => {
  promise_something(request).then(response => {
    sendResponse(response);
  });
});
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您会看到以下错误:Unchecked runtime.lastError: The message port closed before a response was received

要修复此问题,您必须true从异步onMessage侦听器返回。请注意,返回承诺在 chrome 上不起作用(chrome 的文档firefox 的文档)。


kuz*_*gan 12

对我来说,问题是监听器函数是async. 我只是想使用await,但这会导致侦听器返回 aPromise而不是true. 您需要将处理程序包装在异步函数中。

之前(错误):

chrome.runtime.onMessage.addListener(async function (request: any, sender, sendResponse) {
  debug('Got message', request);
  if (request.type === 'updateUser') {
    const responseUser = await getUser();
    user = responseUser;
    await chrome.storage.local.set({ user });
    sendResponse({ user });
  }

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

后:

const handleUpdateUser = async (sendResponse: (response: any) => void) => {
  const responseUser = await getUser();
  user = responseUser;
  await chrome.storage.local.set({ user });
  sendResponse({ user });
};

chrome.runtime.onMessage.addListener(function (request: any, sender, sendResponse) {
  debug('Got message', request);

  if (request.type === 'updateUser') {
    handleUpdateUser(sendResponse);
  }
  
  return true;
})
Run Code Online (Sandbox Code Playgroud)


wor*_*ith 0

供将来参考:我通过将 onMessage/sendMessage 分别切换到后台脚本和内容脚本来解决这个问题。我不知道为什么这有效,但它确实有效。

  • 我希望我明白你的意思。我这两天也遇到同样的问题,已经失去了活下去的勇气…… (8认同)