javascript - 如何处理 "Unchecked runtime.lastError: The message port closed before a response was received"?

标签 javascript google-chrome google-chrome-extension

请原谅我的任何明显错误,因为我是 Chrome 扩展的新手,但 Chrome 消息传递 API 的这个错误已经讨论过 here , here ,和here过去,常见的 react 是“禁用现有的 Chrome 扩展,其中一个导致了错误”。 这是可以实现的最好结果吗?我们是否应该翻身并接受我们的扩展将与其他扩展冲突的事实? 返回 true 或为监听器回调函数返回 Promise 并使用 sendResponse并不能解决我的问题。

目前我只能获取 chrome.storage.local 中存储的新值(没有错误)通过禁用所有其他 chrome 扩展、删除扩展并加载备份解压的扩展。有趣的是,该代码似乎只在developer.chrome.com上工作,它根本不起作用关于 manifest.json 中的其他“匹配”URL .

我认为await有一定的意义。和async运营商正在解决这个问题,但我不确定如何正确实现它。

ma​​nifest.json:

{
    "manifest_version": 2,
    "name": "my extension",
    "version": "1.0",
    "description": "its my extension",
    "permissions": [
        "declarativeContent", 
        "storage", 
        "activeTab"
    ],
    "content_scripts": [
        {
          "matches": [
            "*://developer.chrome.com/*",
            "*://bbc.co.uk/*",
            "*://theguardian.com/*",
            "*://dailymail.co.uk/*"
          ],
          "js": ["content.js"]
        }
      ],
    "background": {
      "scripts": ["background.js"],
      "persistent": false
    },
    "content_security_policy": "script-src 'self' https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js; object-src 'self'",
    "page_action": {
        "default_popup": "popup.html"
    },
    "icons": {
        "16": "images/icon16.png",
        "32": "images/icon32.png",
        "48": "images/icon48.png",
        "128": "images/icon128.png"
      }
}

popup.html:

<!DOCTYPE html>
  <html>
    <head>
      <title>my extension</title>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
      <script src="popup.js"></script>
      <link rel="stylesheet" type="text/css" href="style.css">
    </head>
    <body>
      <h1>my extension</h1>
      <h2>Article: <span id="article-headline"></span></h2>
      <button id="detect-article">Detect Article</button>
    </body>
  </html>

popup.js:

$(document).ready(function() {
    $("#detect-article").click(function() {
        chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
            chrome.tabs.sendMessage(tabs[0].id, {request: "Requesting headline"}, function(response) {
                console.log("Requesting headline")
            });
        });
    });    
})

function getHeadline(changes) {
    let changedValues = Object.keys(changes);
    //console.log(changedValues);

    for (var item of changedValues) {
        console.log("new value: " + changes[item].newValue);
        $("#article-headline").text(changes[item].newValue)
    }
}

chrome.storage.onChanged.addListener(getHeadline);

content.js:

function handleRequest(message, sender, sendResponse) {
    console.log("Request recieved");
    let headlineList = document.getElementsByTagName("h1");
    chrome.storage.local.set({headline: headlineList[0].innerText}, function() {
        console.log("'" + headlineList[0].innerText + "' stored in local storage");
    });
    return true;
}

chrome.runtime.onMessage.addListener(handleRequest);

背景.js:

chrome.runtime.onInstalled.addListener(function() {
    chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
      chrome.declarativeContent.onPageChanged.addRules([{
        conditions: [
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { hostContains: 'developer.chrome.com' },
          }),
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { hostContains: 'bbc.co.uk' },
          }),
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { hostContains: 'theguardian.com' },
          }),
          new chrome.declarativeContent.PageStateMatcher({
              pageUrl: { hostContains: 'dailymail.co.uk' },
          }),
        ],
      actions: [new chrome.declarativeContent.ShowPageAction()]
    }]);
  });
});

非常感谢您花时间查看/重新查看此问题,与上述“禁用现有扩展”相关的解决方案不是我正在寻找的。

最佳答案

当您为 sendMessage 指定回调时,您是在告诉 API 您需要响应,因此当您的内容脚本未使用 sendResponse 进行响应时,API 会认为发生了可怕的事情并进行报告!

Reminder: when editing content scripts make sure to reload both the extension on chrome://extensions page and the tabs that should have this content script.

如果您需要异步运行代码的响应,例如 chrome API 回调:

  • 保持返回true

  • 在回调中调用 sendResponse(someImportantData)

    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      chrome.storage.local.set({foo: 'bar'}, () => {
        sendResponse('whatever');
      });
      return true;
    });
    
  • Promise 相同,但不要对 onMessage 监听器使用 asyncmore info .

    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      fetch(message.url).then(r => r.text())
        .then(t => sendResponse({ok: t}))
        .catch(e => sendResponse({err: e.message}));
      return true;
    });
    

如果您需要回复并且可以立即发送:

  • return true 替换为 sendResponse

    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      sendResponse('whatever');
    });
    

如果您不需要任何回复:

  • 移除sendMessage中的回调

    chrome.tabs.sendMessage(tabs[0].id, {request: "Requesting headline"});
    
  • 删除return true - 它当前所做的只是告诉 API 无限期地保持消息传递端口打开,您永远不会使用该端口,因此它只是一个内存泄漏源。

    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      // do something
      // don't return true
      // ManifestV2: don't call sendResponse
      // ManifestV3 bug: uncomment the next line
      // sendResponse();
    });
    

    对于 ManifestV3 in Chrome 99, 100, 101您需要一个虚拟的 sendResponse() 调用。

关于javascript - 如何处理 "Unchecked runtime.lastError: The message port closed before a response was received"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59914490/

相关文章:

javascript - 如何控制 Javascript 中 window.location 的行为?

php - 有谁知道 ckeditor 的拼写检查器插件使用 aspell 或类似的本地服务而不是 spellchecker.net?

javascript - webview Node 中来自 javascript Selenium chrome webdriver 的警告/错误消息

google-chrome - 当溢出时,最后一个子元素的下边距会被隐藏

javascript - 如何将 Javascript 数组转换为 CSV 文件并从 Chrome 扩展下载?

java - 即使我没有编写要记住的代码,多选框中的选定值也会在第二次加载弹出窗口时被记住

javascript - ui-calendar fullcalendar 中每个事件的自定义按钮

google-chrome - 未通过 Service Worker 传递推送通知

javascript - AJAX POST JSON 数据并接收回 javascript?

javascript - Chrome 扩展 : how to trap/handle content-script errors globally?