runtime.onMessage
Используйте это событие, чтобы прослушивать сообщения из другой части вашего расширения.
Примеры использования:
- в скрипте содержимого, чтобы прослушивать сообщения от скрипта фона.
- в скрипте фона, чтобы прослушивать сообщения от скрипта содержимого.
- в странице настроек или поп-апе скрипте, чтобы прослушивать сообщения от скрипта фона.
- в скрипте фона, чтобы прослушивать сообщения от страницы настроек или скрипта поп-апа.
Чтобы отправить сообщение, которое получит прослушиватель onMessage(), используйте runtime.sendMessage() или (чтобы отправить сообщение скрипту содержимого) tabs.sendMessage().
Примечание: Избегайте создания нескольких onMessage() прослушивателей для одного типа сообщений, так как порядок срабатывания нескольких прослушивателей не гарантирован.
Если вам нужно гарантировать доставку сообщения до определённого пункта назначения, используйте подход, основанный на подключении для обмена сообщениями.
Вместе с самим сообщением прослушиватель получает:
- объект
sender, содержащий подробности об отправителе сообщения. - функцию
sendResponse(), которую можно использовать для отправки ответа отправителю.
Вы можете отправить синхронный ответ на сообщение, вызвав функцию sendResponse() внутри вашего прослушивателя. См. пример.
Для отправки асинхронного ответа есть два варианта:
- вернуть
trueиз обработчика события. Это сохраняет функциюsendResponse()действительной после возврата обработчика, поэтому вы можете вызвать её позже. См. пример. - вернуть
Promiseиз обработчика события, и разрешить его, когда у вас есть ответ (или отклонить его в случае ошибки). См. пример.
Примечание: Вы также можете использовать подход, основанный на подключении для обмена сообщениями.
Синтаксис
browser.runtime.onMessage.addListener(listener) browser.runtime.onMessage.removeListener(listener) browser.runtime.onMessage.hasListener(listener)
События имеют три функции:
addListener(listener)-
Добавляет обработчик к этому событию.
removeListener(listener)-
Прекратить прослушивание этого события. Аргумент
listener— это обработчик, который нужно удалить. hasListener(listener)-
Проверяет, зарегистрирован ли хотя бы один обработчик для этого события. Возвращает
true, если прослушивание активно,false, в противном случае.
Синтаксис addListener
Параметры
listener-
Функция обратного вызова, которая будет вызвана при возникновении этого события. Функции будут переданы следующие аргументы:
message-
object. Само сообщение. Это сериализуемый объект (см. алгоритм клонирования данных). sender-
Объект
runtime.MessageSender, представляющий отправителя сообщения. sendResponse-
Функция, которую нужно вызвать (не более одного раза) для отправки ответа
message. Функция принимает один аргумент, который может быть любым сериализуемым объектом (см. алгоритм клонирования данных). Этот аргумент передаётся обратно отправителю сообщения.Если у вас в одном документе более одного
onMessage()обработчика, то только один может отправить ответ.Для отправки синхронного ответа вызовите
sendResponse()перед возвратом функции-обработчика.Для отправки асинхронного ответа:
- либо сохраните ссылку на аргумент
sendResponse()и вернитеtrueиз функции-обработчика. Тогда вы сможете вызватьsendResponse()после возвращения функции-обработчика. - либо верните
Promiseиз функции-обработчика и разрешите промис, когда ответ будет готов. Это предпочтительный способ.
- либо сохраните ссылку на аргумент
Функция
listenerможет возвращать либо булево значение, либоPromise.Примечание: Если вы передаёте асинхронную функцию в
addListener(), обработчик вернёт промис для каждого полученного сообщения, препятствуя ответам других обработчиков:// don't do this browser.runtime.onMessage.addListener( async (data, sender) => { if (data.type === 'handle_me') { return 'done'; } } );
Если вы хотите, чтобы обработчик реагировал только на сообщения определённого типа, вы должны определить обработчик как не-
asyncфункцию и возвращать промис только для тех сообщений, на которые обработчик должен отвечать — а в остальных случаях возвращать false или undefined:browser.runtime.onMessage.addListener( (data, sender) => { if (data.type === 'handle_me') { return Promise.resolve('done'); } return false; } );
Совместимость с браузерами
| Рабочий стол | Мобильные устройства | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Internet Explorer | Opera | Safari | WebView Android | Chrome Android | Firefox for Android | Opera Android | Safari на iOS | Samsung Internet | |
onMessage |
26 | 14 | 45 | ? | 15 | 14 | ? | ? | 48 | ? | 15 | ? |
return_promise |
Нет | Нет | Да | ? | Нет | 15.4 | ? | ? | Да | ? | 15.4 | ? |
Примеры
Простой пример
Этот скрипт содержимого прослушивает события клика на веб-странице. Если клик был по ссылке, он отправляет сообщение на страницу фона с целевым URL:
// content-script.js window.addEventListener("click", notifyExtension); function notifyExtension(e) { if (e.target.tagName !== "A") { return; } browser.runtime.sendMessage({"url": e.target.href}); }
Скрипт фона прослушивает эти сообщения и отображает уведомление с помощью API notifications:
// background-script.js browser.runtime.onMessage.addListener(notify); function notify(message) { browser.notifications.create({ "type": "basic", "iconUrl": browser.extension.getURL("link.png"), "title": "You clicked a link!", "message": message.url }); }
Отправка синхронного ответа
Этот скрипт содержимого отправляет сообщение на скрипт фона, когда пользователь кликает по странице. Он также регистрирует любой ответ, отправленный скриптом фона:
// content-script.js function handleResponse(message) { console.log(`background script sent a response: ${message.response}`); } function handleError(error) { console.log(`Error: ${error}`); } function sendMessage(e) { const sending = browser.runtime.sendMessage({content: "message from the content script"}); sending.then(handleResponse, handleError); } window.addEventListener("click", sendMessage);
Вот версия соответствующего скрипта фона, который отправляет ответ синхронно, внутри обработчика:
// background-script.js function handleMessage(request, sender, sendResponse) { console.log(`content script sent a message: ${request.content}`); sendResponse({response: "response from background script"}); } browser.runtime.onMessage.addListener(handleMessage);
И вот ещё одна версия, которая использует Promise.resolve():
// background-script.js function handleMessage(request, sender, sendResponse) { console.log(`content script sent a message: ${request.content}`); return Promise.resolve({response: "response from background script"}); } browser.runtime.onMessage.addListener(handleMessage);
Отправка асинхронного ответа с помощью sendResponse
Вот альтернативная версия скрипта фона из предыдущего примера. Он отправляет ответ асинхронно после возвращения обработчика. Обратите внимание на return true; в обработчике: это указывает браузеру, что вы намерены использовать аргумент sendResponse после возвращения обработчика.
// background-script.js function handleMessage(request, sender, sendResponse) { console.log(`content script sent a message: ${request.content}`); setTimeout(() => { sendResponse({response: "async response from background script"}); }, 1000); return true; } browser.runtime.onMessage.addListener(handleMessage);
Отправка асинхронного ответа с помощью промиса
Этот скрипт содержимого получает первую <a> ссылку на странице и отправляет сообщение, спрашивая, занесена ли ссылка в закладки. Он ожидает получить булевый ответ (true если ссылка в закладках, false в противном случае):
// content-script.js const firstLink = document.querySelector("a"); function handleResponse(isBookmarked) { if (isBookmarked) { firstLink.classList.add("bookmarked"); } } browser.runtime.sendMessage({ url: firstLink.href }).then(handleResponse);
Вот скрипт фона. Он использует для проверки, находится ли ссылка в закладках, что возвращает bookmarks.search()Promise:
// background-script.js function isBookmarked(message, sender, response) { return browser.bookmarks.search({ url: message.url }).then((results) => results.length > 0); } browser.runtime.onMessage.addListener(isBookmarked);
Если асинхронный обработчик не возвращает промис, вы можете явно построить промис. Этот довольно искусственный пример отправляет ответ после задержки в 1 секунду, используя setTimeout():
// background-script.js function handleMessage(request, sender, sendResponse) { return new Promise((resolve) => { setTimeout(() => { resolve({response: "async response from background script"}); }, 1000); }); } browser.runtime.onMessage.addListener(handleMessage);
Примеры расширений
- beastify
- content-script-register
- cookie-bg-picker
- devtools-panels
- export-helpers
- find-across-tabs
- imagify
- mocha-client-tests
- notify-link-clicks-i18n
- store-collected-images
- user-script-register
- webpack-modules
Примечание: Этот API основан на API chrome.runtime Chromium. Данная документация взята из runtime.json кода Chromium.
© 2005–2023 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage