Chrome扩展程序长期消息连接 - 如何使用回调函数?

时间:2014-12-09 15:54:45

标签: javascript google-chrome google-chrome-extension

有一段时间我一直在使用chrome.runtime.sendMessage(message, callback)来自我的内容脚本的消息,这些消息需要在从后台收到响应后运行回调函数。

我还有一个长期连接,用于从后台向内容脚本发送消息(不是对内容脚本发起的消息的响应):

backgroundPort = chrome.runtime.connect({ name: "contentScript" });
backgroundPort.onMessage.addListener(function(message){
  if (message["action"] == "something"){
    // Do stuff
  }
});

据我所知,backgroundPort.postMessage() 支持回调消息,这意味着有回调的消息需要使用chrome.runtime.sendMessage()

这种方法的问题在于为每条消息在内容脚本/背景之间建立新连接存在很多开销,所以我试图通过{{将回调功能放入现有的长期连接中1}},但它有点混乱。

任何能够提出优雅解决方案的人?

1 个答案:

答案 0 :(得分:1)

如果将后台脚本视为套接字服务器(Port对象基本上模拟套接字),您可以使用Nodejs,socket.io库中使用的称为“acknowledgement”的东西。

基本上,您将回调函数存储在对象中,方法是为它们提供传递给另一方的唯一标识符。

// on the sending side

// this variable will store callbacks
var acknowledgments = {};

var port = chrome.runtime.connect();

// this variable will be unique callback idetifier
var address = Math.random().toString(36);

// You create acknowledgment by identifying callback
acknowledgments[address] = function (data) {
    // callback function
    // do what you like with result data
};

port.postMessage({
    acknowledgment: address,
    data: messageData
})

port.onMessage.addListener(function (message) {
    var callback = acknowledgments[message.acknowledgment];
    if (callback) {
        callback(message.data);
        // don't forget to unset acknowledgment, because it's 
        // supposed to exists only until it's been called.
        delete acknowledgments[message.acknowledgment];
        return;
    }

    // other message types handling
});

返回该唯一标识符的其他方通行证,通过该标识符可以识别要执行的操作。

// on the listening side
chrome.runtime.onConnect.addListener(function (port) {
    port.onMessage.addListener(function (message) {
        if (message.acknowledgment) {
            // do stuff you need to do
            // then return result
            port.postMessage({
                acknowledgment: message.acknowledgment
                data: stuffYouHaveDoneResult
            });
        }
    });
});

chrome.runtime.sendMessage使用较低级别的“Port”对象,因此sendMessage回调的实际实现原则上应与此类似。