runtime.onMessage
使用此事件监听来自扩展程序其他部分的的消息。
一些示例用例包括:
要发送被 onMessage() 监听器接收的消息,请使用 runtime.sendMessage() 或(要将消息发送到内容脚本) tabs.sendMessage()。
注意: 避免为同一类型的消息创建多个 onMessage() 监听器,因为多个监听器触发的顺序不保证。
如果您想确保消息成功传递到特定端点,请使用 基于连接的消息交换方法。
除了消息本身,监听器还会收到
- 一个
sender对象,其中包含有关消息发送者的详细信息。 - 一个
sendResponse()函数,可用于将响应发送回发送者。
您可以通过在监听器中调用 sendResponse() 函数来发送同步响应。请参阅 发送同步响应示例。
要发送异步响应,有两种选择:
- 从事件监听器返回
true。这会使sendResponse()函数在监听器返回后仍然有效,因此您可以稍后调用它。请参阅 使用sendResponse发送异步响应示例。警告: 不要将
async添加到函数前面。添加async会改变其含义,使其变为 使用 Promise 发送异步响应,这实际上与sendResponse(true)相同。 - 从事件监听器返回一个
Promise,并在准备好响应时解析(或在出错时拒绝)。[请参阅 使用 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 语法
参数
监听器-
此事件发生时调用的函数。该函数会传递以下参数:
message-
object。消息。这是一个可序列化的对象(请参阅 数据克隆算法)。 sender-
一个
runtime.MessageSender对象,表示消息的发送者。 sendResponse-
一个函数,最多调用一次,用于将响应发送回
message。该函数接受一个参数:任何可序列化的对象(请参阅 数据克隆算法)。此参数将传回给消息发送者。如果您在同一文档中有多个
onMessage()监听器,那么只有一个可以发送响应。要同步发送响应,请在监听器函数返回之前调用
sendResponse()。要异步发送响应,请使用以下选项之一:
-
从监听器函数返回一个
Promise,并在响应准备好时解析该 Promise。这是推荐的方法。 -
保留
sendResponse()参数的引用,并从监听器函数中返回true。然后在监听器函数返回后调用sendResponse()。注意: 在 Chrome 中,Promise 作为返回值不受支持,直到 Chrome bug 1185241 解决。作为替代方案,返回 true 并使用 sendResponse。
-
listener函数可以返回布尔值或Promise。注意: 如果您将一个 async 函数传递给
addListener(),监听器将为它收到的每条消息返回一个 Promise,从而阻止其他监听器响应。js// don't do this browser.runtime.onMessage.addListener(async (data, sender) => { if (data.type === "handle_me") { return "done"; } });假设您只想让监听器响应特定类型的消息。在这种情况下,您必须将监听器定义为非 async 函数,并且仅为监听器旨在响应的消息返回 Promise — 否则返回 false 或 undefined。
jsbrowser.runtime.onMessage.addListener((data, sender) => { if (data.type === "handle_me") { return Promise.resolve("done"); } return false; });
示例
简单示例
此内容脚本监听网页上的点击事件。如果点击发生在链接上,它会向背景页面发送一条消息,内容为目标 URL。
// content-script.js
window.addEventListener("click", notifyExtension);
function notifyExtension(e) {
if (e.target.tagName !== "A") {
return;
}
browser.runtime.sendMessage({ url: e.target.href });
}
背景脚本监听这些消息,并使用 notifications API 显示通知。
// 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);
警告: 不要将 async 添加到函数前面。添加 async 会改变其含义,使其变为 使用 Promise 发送异步响应,这实际上与 sendResponse(true) 相同。
使用 Promise 发送异步响应
注意: 在 Chrome 中,Promise 作为返回值不受支持,直到 Chrome bug 1185241 解决。作为替代方案,返回 true 并使用 sendResponse。
此内容脚本获取页面上的第一个 <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);
如果异步处理程序未返回 Promise,您可以显式构造一个 Promise。这个有点牵强的示例使用 setTimeout() 在 1 秒延迟后发送响应。
// 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);
扩展程序示例
浏览器兼容性
加载中…
注意: 此 API 基于 Chromium 的 chrome.runtime API。本文档源自 Chromium 代码中的 runtime.json。