Функция chrome.runtime.onMessage.addListener() вызывается один раз для первого полученного сообщения, но впоследствии она вызывается несколько раз, причем число вызовов увеличивается с каждым последующим сообщением. Пример проблемы приведен на этом изображении: нажмите здесь, чтобы просмотреть изображение
Расширение нацелено на определенную вкладку Chrome, на которой воспроизводится локальный видеофайл, а действия предназначены исключительно для этой вкладки.
Код, вызывающий проблему:
контент.js
// content.js
console.info("--- Start of Content.js --");
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.info("Entered onMessage.addListener")
var video = document.querySelector("video");
if (!video) return;
switch (request.action) {
case "play":
video.play();
break;
case "pause":
video.pause();
break;
case "forward":
video.currentTime += 5;
break;
case "backward":
video.currentTime -= 5;
break;
}
});
фон.js
// background.js
console.info("Background.js");
const urlTest = 'https://api-endpoint.com/get';
function checkAndDoAction() {
fetch(urlTest)
.then(response => response.text())
.then(data => {
if (data !== "None") {
const action_ = data.trim();
queryInfo = {'url': 'file:///Users/username/*'};
chrome.tabs.query(queryInfo, function(tabs) {
chrome.scripting.executeScript({
target: { tabId: tabs[0].id },
files: ["content.js"]
}).then(() => {
console.info("sending msg to content" )
chrome.tabs.sendMessage(tabs[0].id, { action: action_ });
}).catch((error) => {
console.error("Error executing script:", error);
});
});
}
})
.catch(error => console.error("Error:", error));
}
setInterval(checkAndDoAction, 500);
манифест.json
{
"manifest_version": 3,
"name": "Video Controller - extension",
"version": "4.0",
"description": "Browser extension to control video playback.",
"permissions": ["scripting", "tabs", "storage" ],
"host_permissions": ["file:///Users/username/*"],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/playback-16.png",
"48": "icons/playback-48.png",
"128": "icons/playback-128.png"
}
},
"icons": {
"16": "icons/playback-16.png",
"48": "icons/playback-48.png",
"128": "icons/playback-128.png"
},
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
]
}
Я попробовал задать вопрос в чатгпт, ссылаясь на несколько форумов, но ни один из них не помог. Мне нужно найти способ гарантировать, что функция будет запускаться только один раз при каждом вызове.
Вы повторно вводите один и тот же файл несколько раз, он запускается и каждый раз добавляет нового прослушивателя.
Решение: сначала отправьте сообщение, внедрите только в случае неудачи.
chrome.tabs.query({url: '...'}, tabs => tabs.forEach(t => send(t.id, {action: '...'})));
async function send(tabId, msg) {
for (let i = 0; i < 2; i++) {
try {
return await chrome.tabs.sendMessage(tabId, msg);
} catch (err) {
await chrome.scripting.executeScript({
target: { tabId },
files: ['content.js'],
});
}
}
}