序言

最近开发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. sap 常用表

    MM    表名 EBAN 采购申请

  2. C#(asp.net )读取ASHX文件(一般处理程序)

    c#后台获取asxh的返回数据,后台创建一个请求实例,获取请求实例的返回值 public string GetResponseByPost(string apiUrl, string queryStr ...

  3. 有关tp里搜索框的实现方法

    1:

  4. 什么是publickeytoken及publickeytoken的作用

    什么是publickeytoken及publickeytoken的作用 dll的publickeytoken的作用.

  5. WebView网页中使用到支付宝调不起来,提示ERR_UNKNOWN_URL_SCHEME

    转载自:http://blog.csdn.net/u014369799/article/details/51305788 在WebView中如果使用到支付宝,需要添加以下代码,否则操作系统会将支付宝的 ...

  6. springAOP实现基于注解的数据源动态切换

    需求 代码实现读写数据库分离 武器 spring3.0以上版本 实现思路 1.继承org.springframework.jdbc.datasource.lookup.AbstractRoutingD ...

  7. css3选择器总结

    1.p[class^/$/*=td]所有p标签的前面带有td/后面带有td/所有带有td的类的三种样式. 2.div:first-child/last-child/nth-child()在父元素下的第 ...

  8. serialize data use msgpack

    #ifndef _BYTEBUFFER_H #define _BYTEBUFFER_H #include <msgpack.hpp> typedef unsigned char uint8 ...

  9. 查找原始MySQL死锁ID

    转载地址:http://yueliangdao0608.blog.51cto.com/397025/1180917 如果遇到死锁了,怎么解决呢?找到原始的锁ID,然后KILL掉一直持有的那个线程就可以 ...

  10. React jQuery公用组件开发模式及实现

    目前较为流行的react确实有很多优点,例如虚拟dom,单向数据流状态机的思想.还有可复用组件化的思想等等.加上搭配jsx语法和es6,适应之后开发确实快捷很多,值得大家去一试.其实组件化的思想一直在 ...