有一段时间我一直在使用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}},但它有点混乱。
任何能够提出优雅解决方案的人?
答案 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回调的实际实现原则上应与此类似。