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了。这样就可以省去不断打包插件的过程。
于是就出现了这样的情景

咩,竟然是undefined
怪不得onMessage不能触发。难道是浏览器版本问题,上网一通百度,stackoverflow上也有人问相同的问题,结果都没有找到答案,也没有一处说chrome弃用了onMessage方法。就是说onMessage仍然是可用的。为毛我看不到呢?
在最后放弃前我在公司的技术群上吼了一声,看其他人有没有遇到过相同的问题(本人一向低调,能自己百度的东西都不问别人)。后来老大说是我控制台环境不对所以才看不到runtime的其他方法。原来,控制台那里还可以选择插件环境,点top就可以选择。选择了插件环境后,结果真的看到了onMessage方法。

再试下chrome.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页面了

chrome插件开发-消息机制中的bug与解决方案的更多相关文章
- Chrome插件开发入门(二)——消息传递机制
Chrome插件开发入门(二)——消息传递机制 由于插件的js运行环境有区别,所以消息传递机制是一个重要内容.阅读了很多博文,大家已经说得很清楚了,直接转一篇@姬小光 的博文,总结的挺好.后面附一 ...
- vue.js 初体验— Chrome 插件开发实录
欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:陈纬杰 背景 对于经常和动画开发打交道的开发者对于Animate.css这个动画库不会陌生,它把一些常见 ...
- MySQL InnoDB 日志管理机制中的MTR和日志刷盘
1.MTR(mini-transaction) 在MySQL的 InnoDB日志管理机制中,有一个很重要的概念就是MTR.MTR是InnoDB存储擎中一个很重要的用来保证物理写的完整性和持久性的机制. ...
- Chrome插件开发,美化网页上的文件列表。chrome-extension,background
上一篇文章 通过“content-scripts”的方式向页面注入js和css来美化页面,但是有一个弊端:一旦配置好需要注入的页面,之后如果这个页面地址以后发生变化,或者要新加一些URL进来,那么得修 ...
- Chrome插件开发,美化网页上的文件列表。chrome-extension,content-scripts
趁着2018年还剩最后几天,发几篇博客,荒废太久了,惭愧. 最近也是需求驱动,研究了下Chrome插件开发.来看一下我们公司运维提供的日志查看页面 所有项目的日志都参杂在一起,每次去找都很痛苦.慢慢发 ...
- dubbo源码分析2——SPI机制中的SPI实现类的读取和预处理
SPI机制中的SPI实现类的读取和预处理是由ExtensionLoader类的loadFile方法来完成的 loadFile方法的作用是读取dubbo的某个SPI接口的spi描述文件,然后进行缓存,缓 ...
- java多线程机制中的Thread和Runnable()区别
1.java语言使用Thread类及其子类对象来表示线程,新建的一个线程声明周期中经历 新建.(声明一个线程,此时他已经有了相应的内存空间和其他资源),运行(线程创建之久就据用了运行的条件,一旦轮到使 ...
- Linux内存管理机制中buffer和cache的区别
Linux内存管理机制中buffer和cache的区别理解linux内存管理,需要深入了解linux内存的各个参数含义和规则,下面介绍一下Linux操作系统中内存buffer和cache的区别. Fr ...
- Java 反照机制中 getMethod()和getDeclaredField()区别
Java 反射机制中 getMethod()和getDeclaredField()区别 今天在程序中用到java反射机制时,遇到的问题记录一下:我当时遇到的问题是,我用反射getMethod()调用类 ...
随机推荐
- flash中字体兼容性
非谷歌浏览器设置字体font时需设置为该字体的(英文名字)或者(中文名字+可读性消除锯齿), 谷歌浏览器设置字体font时需设置为该字体的(中文名字) 总结:静态文本一般通过选择可读性消除锯齿来能实现 ...
- Myeclipse 安装离线adt的方法 ()
方法一: 1.下载最新的adt插件ADT-10.0.1.zip (在MyEclipse 10.5 上安装的ADT插件是ADT 20.0.3离线包下载地址: http://dl.cr173.com//s ...
- loadView、viewDidLoad、viewWillAppear、viewDidAppear等详解
loadView; This is where subclasses should create their custom view hierarchy if they aren't using a ...
- iOS10字体
iOS10字体随着手机系统的字体改变,当我们手机系统字体改变以后,我们的app的lable也会跟着一起变化: 同样的6sp,在iOS9上面运行字体显示是没问题的,当我的手机更新了iOS10以后,有的界 ...
- c#输出、输入
//输出 Console.WriteLine("这是一行文字"); 自动回车的. Console.Write("Hello world"); 不带回车的. ...
- bootstrap-datepicker使用
$('.date').datepicker({ language: 'zh-CN', --指定格式 format: 'yyyy-mm', --格式要求 autoclose: true, --选择后是否 ...
- C++ exe调用dll文件
生成dll程序 extern "C"_declspec(dllexport) void maopao(int *p,int count);void maopao(int *p,in ...
- 在ASP.NET MVC中使用Juqery实现页面局部刷新
自己做的一个实验,留作备忘,此实例包括扩一下几个文件: 1.MyMovieController.cs 2.Index.aspx 3.ViewUserControl1.ascx 4.movie类 其中M ...
- CSS实现完美垂直居中
之前看到很多人一直都问这个问题,不过当时我没当一回事,因为在 CSS 中要垂直居中,多数是在有高度的情况下,或者容器高度不定的情况下才用,看上去比较舒服,而且实现的方法也不少,不一定要拘泥于和 tab ...
- python基础第三天(1)
函数 函数分为:内置函数,自定义函数,导入函数. 内置函数 python为咱们提供的快捷方式 vars()---针对脚本的,找到这个脚本中的所有变量. #!/usr/bin/env python # ...