将消息从一个听众传递到另一个听众 [英] Passing message from one listener to another

查看:110
本文介绍了将消息从一个听众传递到另一个听众的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发Chrome的扩展程序,以下是我尝试实现的工作流程:

弹出发送消息 - >内容脚本1侦听 - >内容脚本1发送消息 - >内容脚本2监听 - >内容脚本2执行动作

概念上它很好,很花哨;我所做的是设置了2个监听器:每个内容脚本中都有一个监听器:

弹出式菜单:

<$ p $ $ {code> chrome.tabs.query({active:true,currentWindow:true},function(tabs){
console.log('popup发送请求');
chrome。 tabs.sendMessage(tabs [0] .id,obj);
});

内容脚本1:

  chrome.runtime.onMessage.addListener((function(request,sender){
this.log('wg got request','request',request,'sender',sender);
if(request.action =='options-updated'){
this.updateOptions(request,(function(){
var obj = {action:'refresh',WG:window .WG};
this.log('wg转发的请求');
chrome.runtime.sendMessage(obj); //尝试转发另一个请求
返回true;
})。bind(this));
}
return true;
})。bind(window.WG));

内容脚本2:

  chrome.runtime.onMessage.addListener(function(request,sender,sendResponse){
console.log('content script got request','request',request,'sender',sender );
if(request.WG){
request.WG.log('message',request.action);
if(request.action =='refresh'){
WGRefresh(request.WG,request.options);
}
}
返回true;
});

问题是,内容脚本2只收到第一条消息。因此,我得到的输出是:

弹出发送请求
内容脚本获取请求(首先忽略)
wg获取请求(相同,首先不要在这里忽略)
wg转发请求

然后没事。内容脚本应该再次触发它,并且在请求中我总是发送action,这是我在listener中检查的,但是对于我没有区分的日志(它应该总是记录,所以这意味着请求永远不会被获取那里)。

我已经试过在所有的听众中都返回true,根据文档,它会保持链条运行并且不会在第一次击中后停止,但即使如此它不工作。有什么我做错了!

解决方案

有2 sendMessage 函数在Chrome API中。





因此,在第一个内容脚本中调用 chrome.runtime.sendMessage()无法访问任何其他内容脚本。



更重要的是,您不能直接从 chrome.tabs 一个内容脚本。



为了做到你想做的事,你需要设置一个后台脚本,它将像代理服务器b一样工作在CS1和CS2之间。从技术上讲,你可以使用弹出窗口,但它不可靠,因为弹出窗口可能会关闭,然后没人会听。背景页面(或更好的是活动页面)专为此目的而设计。 tabs.sendMessage ) - > CS1 - ( runtime .sendMessage ) - > background - ( tabs.sendMessage ) - > CS2



请注意,背景页面需要知道发送消息的标签ID。如果由于某种原因它是相同的标签,例如您试图通过帧传递消息,您可以在回调中使用 sender 参数。



请参阅消息文档了解更多详情。


I'm developing an extension for Chrome, and here's the workflow I'm trying to achieve:

popup sends message -> content script 1 listens -> content script 1 sends message -> content script 2 listens -> content script 2 performs action

In concept it's fine and dandy; what I've done is set up 2 listeners: one in each content script:

Popup:

chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
                console.log('popup send request');
                chrome.tabs.sendMessage(tabs[0].id, obj);
            });

Content script 1:

chrome.runtime.onMessage.addListener((function (request, sender) {
    this.log('wg got request', 'request', request, 'sender', sender);
    if (request.action == 'options-updated') {
        this.updateOptions(request, (function() {
            var obj = {action: 'refresh', WG: window.WG};
            this.log('wg forwarded request');
            chrome.runtime.sendMessage(obj); // attempting to forward another request
            return true;
        }).bind(this));
    }
    return true;
}).bind(window.WG));

Content script 2:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    console.log('content script got request', 'request', request, 'sender', sender);
    if (request.WG) {
        request.WG.log('message', request.action);
        if (request.action == 'refresh') {
            WGRefresh(request.WG, request.options);
        }
    }
    return true;
});

Problem is, content script 2 only receives the first message. So the output I'm getting is:

popup send request content script got request (first, to ignore) wg got request (same, first, don't ignore here) wg forward request

And then nothing. The content script should have fired it again, and in the request I always send "action", which I check for in the listener, but for the logs I don't differentiate (it should ALWAYS log, so this means the request never gets there).

I've tried returning true in all the listeners, according to the documentation it will keep the chain running and not stop after the first hit, but even so it's not working. What am I doing wrong?!

解决方案

There are 2 sendMessage functions in Chrome API.

So the call to chrome.runtime.sendMessage() in your first content script can't reach any other content script.

What's more, you can't call chrome.tabs directly from a content script.

To do what you want, you need to set up a background script that will act like a proxy between CS1 and CS2. Technically, you could use the popup, but it's unreliable, as the popup may be closed and then nobody would be listening. The background page (or better yet, an event page) is designed specifically for that purpose.

So the scheme becomes: popup -(tabs.sendMessage)-> CS1 -(runtime.sendMessage)-> background -(tabs.sendMessage)-> CS2

Do note that background page will need to know the tab ID to send the message to. If it's the same tab for some reason, e.g. you're trying to message across frames, you can use the sender parameter in the callback.

See Messaging docs for more details.

这篇关于将消息从一个听众传递到另一个听众的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆