序言

最近开发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与解决方案的更多相关文章

  1. Chrome插件开发入门(二)——消息传递机制

    Chrome插件开发入门(二)——消息传递机制   由于插件的js运行环境有区别,所以消息传递机制是一个重要内容.阅读了很多博文,大家已经说得很清楚了,直接转一篇@姬小光 的博文,总结的挺好.后面附一 ...

  2. vue.js 初体验— Chrome 插件开发实录

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:陈纬杰 背景 对于经常和动画开发打交道的开发者对于Animate.css这个动画库不会陌生,它把一些常见 ...

  3. MySQL InnoDB 日志管理机制中的MTR和日志刷盘

    1.MTR(mini-transaction) 在MySQL的 InnoDB日志管理机制中,有一个很重要的概念就是MTR.MTR是InnoDB存储擎中一个很重要的用来保证物理写的完整性和持久性的机制. ...

  4. Chrome插件开发,美化网页上的文件列表。chrome-extension,background

    上一篇文章 通过“content-scripts”的方式向页面注入js和css来美化页面,但是有一个弊端:一旦配置好需要注入的页面,之后如果这个页面地址以后发生变化,或者要新加一些URL进来,那么得修 ...

  5. Chrome插件开发,美化网页上的文件列表。chrome-extension,content-scripts

    趁着2018年还剩最后几天,发几篇博客,荒废太久了,惭愧. 最近也是需求驱动,研究了下Chrome插件开发.来看一下我们公司运维提供的日志查看页面 所有项目的日志都参杂在一起,每次去找都很痛苦.慢慢发 ...

  6. dubbo源码分析2——SPI机制中的SPI实现类的读取和预处理

    SPI机制中的SPI实现类的读取和预处理是由ExtensionLoader类的loadFile方法来完成的 loadFile方法的作用是读取dubbo的某个SPI接口的spi描述文件,然后进行缓存,缓 ...

  7. java多线程机制中的Thread和Runnable()区别

    1.java语言使用Thread类及其子类对象来表示线程,新建的一个线程声明周期中经历 新建.(声明一个线程,此时他已经有了相应的内存空间和其他资源),运行(线程创建之久就据用了运行的条件,一旦轮到使 ...

  8. Linux内存管理机制中buffer和cache的区别

    Linux内存管理机制中buffer和cache的区别理解linux内存管理,需要深入了解linux内存的各个参数含义和规则,下面介绍一下Linux操作系统中内存buffer和cache的区别. Fr ...

  9. Java 反照机制中 getMethod()和getDeclaredField()区别

    Java 反射机制中 getMethod()和getDeclaredField()区别 今天在程序中用到java反射机制时,遇到的问题记录一下:我当时遇到的问题是,我用反射getMethod()调用类 ...

随机推荐

  1. UItextFiled只能输入数字

    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementS ...

  2. github 添加项目

    下载git安装 ->https://git-scm.com/downloads 新建git目录 在目录下右键选择Git Bash Here 执行 git init 拷贝项目到git目录下 在gi ...

  3. C++读写文件ofstream,ifstream,fstream)[转]

    在看C++编程思想中,每个练习基本都是使用ofstream,ifstream,fstream,以前粗略知道其用法和含义,在看了几位大牛的博文后,进行整理和总结: 这里主要是讨论fstream的内容:[ ...

  4. JS编写全选,复选按钮

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  5. (转)jquery easyui treegrid使用小结 (主要讲的是如何编辑easyui中的行信息包括添加 下拉列表等)

    在实际应用中可能会碰到不同的需求,比如会根据每行不同的参数或属性设置来设置同列不同的editor类型,这时原有的例子就显的有点太过简单,不能实现我们的需求,现在应用我在项目中的操作为例,显示下实现同列 ...

  6. Python:线程

    Python中创建线程有两种方式:函数或者用类来创建线程对象. 函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程. 类:创建threading.Thread的 ...

  7. [问题记录.VisualStudio]TFS项目映射问题解决

    [问题描述] Visual Studio 2013 中打开用TFS源码管理的项目失败! 1.对特定的项目,不管是通过解决方案文件(.sln)还是项目文件(.csproj)打开,都显示项目无法加载. 2 ...

  8. 等宽字体延伸到的 ch 长度单位和动画 animation-timing-function

    新知识点get! 等宽字体(monospaced font)是指字符宽度相同的电脑字体.与此相对,字符宽度不尽相同的电脑字体称为比例字体(proportional font). 东亚字体基本都是等宽字 ...

  9. Python 基本语法 学习之路(三)

    定义变量 在Python中,定义一个变量是很简单的.而且,在Python中,定义是不需要用分号结尾的.例如: a = 10 b = 3 print(a*b) 判断语句 Pyhon的if判断语句是由if ...

  10. 云存储的那些事(2)——数据分布算法CRUSH

    在分布式系统中,数据最终还是要存储到物理设备上的,ceph的底层设备抽象角色是OSD,那么数据是如何被决定放在哪块OSD上的,答案就是CRUSH算法. 关键字:CRUSH.一致性hash.ceph数据 ...