代码之家  ›  专栏  ›  技术社区  ›  Alexander

Chrome扩展消息传递:未选中运行时.lastError:无法建立连接。接收端不存在

  •  2
  • Alexander  · 技术社区  · 7 年前

    我的chrome扩展有以下两个javascripts:

    background.js

    chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
        if (message.data == "takeScreenshot") {
            var resp = sendResponse;
            chrome.tabs.captureVisibleTab(function(screenshotUrl) {
                resp({
                    screenshot: screenshotUrl
                });
            });
            return true; // Return true to tell that the response is sent asynchronously
        } else {
            return "TestReply";
        }
    });
    

    api.js

    window.takeScreenshot = (function() {
        var isTakingScreenshot = false; // Semaphore
        return function() {
            if(isTakingScreenshot) return Promise.reject();
            isTakingScreenshot = true;
            return new Promise(function(resolve, reject) {
                chrome.runtime.sendMessage("eomfljlchjpefnempfimgminjnegpjod", "takeScreenshot", function(response) {
                    console.log(response);
                    isTakingScreenshot = false;
                    resolve(response.screenshot);
                });
            });
        }
    })()
    window.test = (function() {
        return function() {
            return new Promise(function(resolve, reject) {
                chrome.runtime.sendMessage("eomfljlchjpefnempfimgminjnegpjod", "test", function(response) {
                    console.log(response);
                    resolve(response.length);
                });         
            });
        }
    })();
    

    当我在选项卡的控制台中执行任意一个函数时(auto complete知道它们,所以它们可用),我得到一个错误:

    未检查运行时.lastError:无法建立连接。接收端不存在。

    返回的响应是未定义的。

    我已经查过身份证了 sendMessage 与舱单和chrome://扩展页,我打开了扩展的后台页面DevTools,并在那里手动添加了相同的侦听器,以确保侦听器确实已注册。

    1 回复  |  直到 7 年前
        1
  •  21
  •   David Dehghan    7 年前

    好 啊。我发现了问题所在。我想这是自72年以来chromes行为的一个变化。问题是如果你想打电话chrome.runtime.connect()在后台或弹出页面中打开另一端的频道之前,将出现该错误。

    ChromeDocs说的是你可以立即发送消息。在过去,这只会起作用,消息要么被传递,要么被丢弃。但现在它失败了。

    chrome docs :呼叫时tabs.connect.连接, 运行时.connect或者runtime.connectNative,将创建一个端口。此端口可立即用于通过postMessage向另一端发送消息。

    因此,我们的解决方法是在调用connect()之前先设置连接侦听器,只需延迟connect()调用:

        chrome.runtime.onConnect.addListener(port => {
            console.log('connected ', port);
    
            if (port.name === 'hi') {
                port.onMessage.addListener(this.processMessage);
            }
        });
    

    如果您在内容脚本端为disconnect事件设置了侦听器,那么当您尝试时,它实际上会被调用chrome.runtime.connect你在另一端没有任何东西在听。哪种行为是正确的 Port LifeTime

       port = chrome.runtime.connect(null, {name: 'hi'});      
       port.onDisconnect.addListener(obj => {
                console.log('disconnected port');
        })
    

    我不知道有没有比setTimeout和尝试获取chrome.runtime.connect在那之后chrome.runtime.onConnect.addListener被调用。这不是一个好的解决方案,因为它会导致计时错误。也许另一个解决方法是反转通道的方向。并启动connectfrom popup而不是contentscript。

    更新 a minimum repro extension

        2
  •  10
  •   Márton György    6 年前

    这是我用来解决这个问题的一个模式。内容脚本尝试到达背景脚本。如果后台脚本还不可用,那么我们可以从 chrome.runtime.lastError

    function ping() {
      chrome.runtime.sendMessage('ping', response => {
        if(chrome.runtime.lastError) {
          setTimeout(ping, 1000);
        } else {
          // Do whatever you want, background script is ready now
        }
      });
    }
    
    ping();
    

    背景脚本.js

    chrome.runtime.onConnect.addListener(port => {
      port.onMessage.addListener(msg => {
        // Handle message however you want
      }
    );
    
    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => sendResponse('pong'));
    
        3
  •  3
  •   clhenrick    6 年前

    如果您在开发Chrome扩展时收到此错误消息,请确保禁用您在浏览器中安装的其他Chrome扩展。尤其是“AdBlock”扩展似乎干扰了消息传递,并导致我的扩展抛出此错误。禁用AdBlock为我解决了这个问题。

        4
  •  2
  •   TrophyGeek    5 年前

    使用的调用是

    1. 从背景页:

    chrome.runtime.onMessageExternal.addListener 注意 部分。

    1. manifest.json
          "externally_connectable": {
            "ids": ["abcdefghijklmnopqrstuvwxyzabcdef"],
            "matches": ["https://example.com/*"],
            "accepts_tls_channel_id": false
          },
    

    "abcdefghijklmnopqrstuvwxyzabcdef" 是您的分机号。

    "https://example.com/*"

    1. chrome.runtime.sendMessage chrome.runtime.connect 用一个 extensionId

    https://developer.chrome.com/extensions/manifest/externally_connectable