#Chrome扩展程序开发教程--07:消息传递

引言

        本系列博客旨在带来最新的Chrome扩展程序开发入门教程。


1、基本介绍

        因为 content scripts 是注入到网页中运行的,不能直接和扩展程序其它部分共享环境和变量,所以需要一些方式来与扩展程序的其它部分进行通信。扩展程序中的任何一方都可以监听从另一端发出的消息,并在同一通道上作出回应。消息可以是任何有效的 JSON 对象(null、布尔值、数字、字符串、数组或对象)。

2、简单通信

        简单通讯适用于单次的即时消息发送,chrome.runtime对象中内置了一个消息通道,可以直接发送。从 content scripts 向 service worker 发送消息的代码如下所示:

(async () => {
  const response = await chrome.runtime.sendMessage({greeting: "hello"});
  // do something with response here, not outside the function
  console.log(response);
})();

        如果需要从 service worker 向 content scripts 发送消息的话,则需要指定 tab 对象:

(async () => {
  const [tab] = await chrome.tabs.query({active: true, lastFocusedWindow: true});
  const response = await chrome.tabs.sendMessage(tab.id, {greeting: "hello"});
  // do something with response here, not outside the function
  console.log(response);
})();

        无论接收方是 service worker 或 content scripts ,只需要添加接收消息的监听器即可:

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"});
   	return true;
  }
);

        但需要注意的是,如果存在多个接收方,那么只有第一个调用 sendResponse 的接收方返回的消息才能被发送方接收。

3、长时间通信

        有些时候,扩展程序中的部分模块之间需要进行长时间稳定通信,此时在用上面那种通信方法就不太合适了。
        以下代码为从 content scripts 向 service worker 发送建立连接请求。其中 connect 的时候可以指定 name 属性,用以区分不同目的和功能的连接。

var port = chrome.runtime.connect({name: "knockknock"});
port.postMessage({joke: "Knock knock"});
port.onMessage.addListener(function(msg) {
  if (msg.question === "Who's there?")
    port.postMessage({answer: "Madame"});
  else if (msg.question === "Madame who?")
    port.postMessage({answer: "Madame... Bovary"});
});

        如果需要从 service worker 向 content scripts 发送建立连接请求,则需要指定 tab 对象,和简单通信中的做法类似。
        无论接收方是 service worker 或 content scripts ,只需要添加接收连接的监听器即可:

chrome.runtime.onConnect.addListener(function(port) {
  console.assert(port.name === "knockknock");
  port.onMessage.addListener(function(msg) {
    if (msg.joke === "Knock knock")
      port.postMessage({question: "Who's there?"});
    else if (msg.answer === "Madame")
      port.postMessage({question: "Madame who?"});
    else if (msg.answer === "Madame... Bovary")
      port.postMessage({question: "I don't get it."});
  });
});

        这里面的 port 就是连接的双方用来进行通信的对象,但其中有一些细节需要注意一下:
        当从 service worker 向 content scripts 发送建立连接请求时,若目标 tab 中存在多个 frame ,且 content scripts 注入到了每个 frame 中,则每个 frame 中的 runtime.onConnect 事件都会被触发。同样的,也可能会出现多个 frame 中的 runtime.connect() 一起调用的情况。

4、其它通信

        主要用到的就是上面介绍的两种通信手段,但还存在另外的通信,除非特殊目的,否则不会用到的,因此这里只简单介绍一下:

4.1、Cross-extension messaging

        除了在自己的扩展程序中的不同组件之间进行通信外,还可以使用消息传递 API 与其他扩展程序进行通信。

4.2、Sending messages from web pages

        与 Cross-extension messaging 一样,扩展程序可以接收和响应来自普通网页的消息。

4.3、Native messaging

        扩展程序可以与主机上的应用程序进行通信。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值