zoukankan      html  css  js  c++  java
  • chrome插件开发-消息机制中的bug与解决方案

    序言

    最近开发chrome插件,涉及到消息传递机时按照教程去敲代码,结果总是不对。研究了大半天终于找到原因,现在记录下。

    程序

    插件程序参考官网 chrome官网之消息传递机制, 不能翻墙的同事也可以参考下这位牛人的文章 [chrome插件开发之消息传递机制](http://ju.outofmemory.cn/entry/74567 "chrome插件开发之消息传递机制")

    感谢这些牛人的分享让我们学到了很多知识。

    这篇大牛的文章中有content向background传递消息的按钮,亲测是没问题。当时没有background向content传递消息的方法,自己动手没有成功,后来就找到了chrome管网,直接复制官网程序也没成功。官网的案例程序程序如下,不能翻墙的童鞋可以看这里:

    background.js

    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
      chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
        console.log(response.farewell);
      });
    });
    

    content.js

    chrome.runtime.onMessage.addListener(
      function(request, sender, sendResponse) {
        console.log(sender.tab ?
                    "from a content script:" + sender.tab.url :
                    "from the extension");
        if (request.greeting == "hello")
          sendResponse({farewell: "goodbye"});
      });
    

    bug

    没有成功的原因看起来像是content页面的chrome.runtime.onMessage没有触发。之前看介绍说content.js等同于页面上的js,那我就想当然的以为可以在控制台调试content.js了。这样就可以省去不断打包插件的过程。
    于是就出现了这样的情景

    runtime

    咩,竟然是undefined

    怪不得onMessage不能触发。难道是浏览器版本问题,上网一通百度,stackoverflow上也有人问相同的问题,结果都没有找到答案,也没有一处说chrome弃用了onMessage方法。就是说onMessage仍然是可用的。为毛我看不到呢?

    在最后放弃前我在公司的技术群上吼了一声,看其他人有没有遇到过相同的问题(本人一向低调,能自己百度的东西都不问别人)。后来老大说是我控制台环境不对所以才看不到runtime的其他方法。原来,控制台那里还可以选择插件环境,点top就可以选择。选择了插件环境后,结果真的看到了onMessage方法。

    插件环境

    再试下chrome.runtime

    插件runtime

    问题

    现在问题又来啦,既然有onMessage方法,那为啥content没有响应呢?找个原因又是花几万字都说不完的过程了。

    废话少说了,要扣工资了。就是经过大量的测试和实验,终于找到了原因。

    1、案例的background.js代码中currentWindow是有害的,这个导致background不能发送消息,需要去掉。我也不知道为什么,知道的大神麻烦说下。

    2、chrome的background.js是只执行一次的,当你安装插件后,打开一个页面看测试结果的时候,其实background已经把消息传给了content。并且content也成功接收了。但是因为你是打开页面后才打开发开发者工具的,开发者工具不会显示之前的消息,所以开发者工具是空白的。之后你再刷新,background都不会再运行,控制台就始终是空白。看起来就好像content中onMessage方法失效了一样

    新代码如下

    background.js

    chrome.tabs.onUpdated.addListener(
    	function(tabId,info,tab){
    		if(info.status=="complete")
    			console.log("complete")
    		chrome.tabs.sendMessage(tabId, {greeting: "inupdate"}, function(response) {
    			console.log(response);
    		});
    	}
    )
    

    我的程序每次tab有更新的时候就运行一次background。这样你打开控制台再刷新就可以看到消息传递的结果。如果你想跟案例代码一样,让background只运行一次的话,可以改成这样。跟案例代码的区别只是去掉了currentWindow

    background.js(去掉了currentWindow)

    chrome.tabs.query({active: true}, function(tabs) {
      console.log("tabs",tabs)
      console.log("tabs[0].id",tabs[0].id)
      chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
        console.log(response);
      });
    });
    

    之前我有试过使用runtime.sendMessage发送消息。当是这样子是有问题。
    原文如下
    chrome.runtime.sendMessage sends a message to all open extension pages (i.e. background, popup, etc.)
    chrome.tabs.sendMessage sends a message to all content scripts from the extension in a given tab
    大概意思是runtime会发送消息给所有打开的扩展页面比如背景或者popup,而tabs是给被被打开的标签页的所有content发消息。两侧

    content.js

    content跟官网的案例基本上一样,我只是添加了一个自己的打印语句

    chrome.runtime.onMessage.addListener(
      function(request, sender, sendResponse) {
        console.log(sender.tab ?
                    "from a content script:" + sender.tab.url :
                    "from the extension");
        if (request.greeting == "hello"){
        	sendResponse({farewell: "goodbye"});
        }
        else if(request.greeting =="inupdate"){
        	sendResponse({farewell:"getUpdate"})
        } 
     });
    

    这样子就没问题,background就可以传递消息给content了。ps下background的调试技巧。点击下这里就可以调试background页面了

  • 相关阅读:
    记录一些笔记~
    JS里的居民们7-对象和数组转换
    JS里的居民们6-数组排序
    JS里的居民们5-数组(栈)
    MySQL设置当前时间为默认值的方法
    session过期问题
    MyIsam和InnoDB的区别
    ajax请求 json格式和数组格式总结
    wamp 2.5 开放访问权限和设置虚拟域名
    checkbox属性checked="checked"通过js已设置,但是不勾选
  • 原文地址:https://www.cnblogs.com/gg1234/p/5916283.html
Copyright © 2011-2022 走看看