Я пишу расширение для браузера Firefox и застрял в том, как ждать загрузки скрипта контента перед отправкой сообщения из фонового скрипта. Вот последовательность, которую я пытаюсь выполнить:
- Пользователь щелкает элемент контекстного меню (обработчик кликов находится в фоновом скрипте)
- Фоновый скрипт создает новую вкладку
- Скрипт контента полностью загружается в новой вкладке
- Фоновый скрипт отправляет сообщение (с данными) в скрипт контента
- Скрипт контента использует данные
Очевидно, скрипту контента нужно быть загруженным для шага 4, чтобы работать; в противном случае сообщение не будет получено.
Я посмотрел предыдущие подобные вопросы, но большинство ответов неверны (они оборачивают методы прослушивателя событий в Promise, что приводит либо к слишком большому числу слушателей, либо к слишком большому числу слушателей). несколько обещаний), или они кажутся неприменимыми к моему сценарию (эти ответы полностью решают вопрос, помещая один обратный вызов внутрь другого; это не сработает здесь).
То, что я пробовал до сих пор, было чтобы скрипт содержимого отправлял сообщение, когда он готов, и это работает, но я до сих пор не уверен, как заставить обработчик щелчка (из шага 1) ожидать сообщения из скрипта контента (гипотетический шаг 3.5). Я предполагаю, что мне придется определять обработчик сообщений вне обработчика щелчков, насколько я знаю, если только нет способа получить сообщение внутри обработчика щелчков.
Вот мой текущий код в качестве минимального рабочего примера :
background.js
:
let ports = {
'1': null,
'2': null
};
xyz = () => { /*...*/ }
tabHasLoaded = () => { /*...*/ }
browser.runtime.onConnect.addListener(connectHandler);
connectHandler = (p) => {
ports[p.name] = p;
switch (p.name) {
case '1':
ports['1'].addListener(xyz);
break;
case '2':
ports['2'].addListener(tabHasLoaded);
break;
}
};
browser.contextMenus.onClicked.addListener((info, tab) => {
let data, uri;
//...
browser.tabs.create({
url: uri
}).then((tab) => {
// need to wait for tabHasLoaded() to get called
ports['2'].postMessage({
msg: data
})
});
});
1.js
(скрипт содержимого для чего-то другого):
let myPort = browser.runtime.connect({
name: '1'
});
document.addEventListener("click", (e) => {
myPort.postMessage({
msg: e.target.id
});
});
2.js
(скрипт контента для новой вкладки, после нажатия контекстного меню):
let myPort = browser.runtime.connect({
name: '2'
});
myPort.postMessage({
msg: "READY" // tabHasLoaded() should now get called in background.js
});
myPort.onMessage.addListener((msg) => {
// waiting for background.js to send me data
});
Есть ли идеальный способ справиться с этим?