我正在将国际象棋游戏解析器移植到新的 list v3 规范。单击选定文本
上的上下文菜单时,它会以可视方式将选定文本
播放为 PGN国际象棋游戏符号。
问题在于,每次游戏执行时的后台脚本都会添加一个 chrome.runtime.onMessage 监听器,并且所有监听器都会持续存在,直到浏览器关闭。因此,所有监听器都会被调用,并且每次只玩第一个游戏。
有代码:
//background.js
function playBoard (info, imgPath, windowAttributes)
{
console.log("play board with: " + info.selectionText);
let gameObject = {
chessObject:
{
gametype : "PGN_OR_FEN_board",
content : info.selectionText,
imgPath : imgPath
}
};
let windowPromise = chrome.windows.create(windowAttributes);
windowPromise.then((value) => {
chrome.runtime.onMessage.addListener(
(request, sender, sendResponse) =>
{
console.log("backg: chrome.runtime.onMessage()> " + gameObject.chessObject.content);
sendResponse(gameObject);
}
);
});
}
上面的代码在以下上下文中调用:
//background.js
console.log("enter global>");
var idParser = "parser parent";
var idMiniBoard = "board mini";
var idMediuBoard = "board medium";
chrome.runtime.onInstalled.addListener(
(details)=>
{
console.log("on installing");
idParser = chrome.contextMenus.create({"id":idParser, "title": "Chess Parser", "contexts":["selection"]});
idMiniBoard = chrome.contextMenus.create({"id":idMiniBoard, "title": "Play Small", "contexts":["selection"], "parentId": idRoatta});
idMediuBoard = chrome.contextMenus.create({"id":idMediuBoard, "title": "Play Medium", "contexts":["selection"], "parentId": idRoatta});
chrome.contextMenus.onClicked.addListener(menuItemClick);
console.log("on installed");
}
)
function menuItemClick(clickData, tab)
{
switch (clickData.menuItemId)
{
case idMiniBoard:
playBoard (clickData, "mini18", {url: "board.html", type:"popup", height : 350, width : 350});
return;
case idMediuBoard:
playBoard (clickData, "medium35", {url: "board.html", type:"popup", height: 450, width: 450});
return;
}
}
有弹窗启动代码
document.addEventListener('DOMContentLoaded',
(event) =>
{
chrome.runtime.sendMessage({ chessObject: { gametype : "PGN_OR_FEN_board" } },
(request) => //in fact is response, but is requested response
{
board_doc_main(request.chessObject);
});
}
);
我正在尝试应用与 Firefox 类似的方法,此处 Firefox extension, identification of context 。不知何故,对于 Firefox 来说,这是可行的。我正在尝试这样实现:从后台工作人员单击时弹出窗口打开。然后弹出窗口向后台工作人员发送消息以接收所需的上下文,包括选择游戏文本
。
###################
更新:
正如 @wOxxOm 的回复所建议的,这正是我现在改变的方式
function playBoard (clickData, imgPath, windowAttributes)
{
let gameObject = {
chessObject:
{
gametype : "PGN_OR_FEN_board",
content : clickData.selectionText,
imgPath : imgPath
}
};
let windowPromise = chrome.windows.create(windowAttributes);
windowPromise.then((wnd) => {
chrome.runtime.onMessage.addListener (
function __playBoardCallback__ (request, sender, sendResponse)
{
if (sender.tab?.id === wnd.tabs[0].id)
{
chrome.runtime.onMessage.removeListener(__playBoardCallback__);
sendResponse(gameObject);
}
}
);
});
}
最佳答案
使用命名函数运行时立即取消注册监听器:
async function playBoard(info, imgPath, windowAttributes) {
let gameObject = {
// .........
};
const wnd = await chrome.windows.create(windowAttributes);
const tabId = wnd.tabs[0].id;
chrome.runtime.onMessage.addListener(function _(msg, sender, sendResponse) {
if (sender.tab?.id === tabId) {
chrome.runtime.onMessage.removeListener(_);
sendResponse(gameObject);
}
});
}
关于javascript - 在扩展中,回调会累积并持续到浏览器重新启动为止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74933234/