跳到主要内容

Web 网页使用 postmessage 与 Chrome 扩展通讯支持 promise

· 阅读需 3 分钟
givebest

浏览器网页可以很方便的使用 postmessage 与 Chrome 扩展通讯,但是 postmessage 只能传递消息,不能传递 promise,如果遇到网页需要等待 Chrome 扩展返回的 promise,处理起来就比较麻烦了。

现在可以通过封装 postmessage 发送消息 和 监听 message 接收消息,然后直接返回 promise,这下就方便多了。

网页发送并接收 promise 消息

<html lang="en">
<head>
<meta charset="UTF-8" />
<title>test chrome extension</title>
</head>

<body>
<div id="btns">
<button class="install">测试发送并接收消息</button>
</div>

<script>
async function waitForPostMessage({
timeout = 5000,
type,
data = {},
lang,
}) {
const returnType = `RETURN_${type}`;
let timeoutId = null;

window.postMessage({
type: type,
data: { ...data, timeout, lang },
});

const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error("timeout"));
}, timeout);
});

const responsePromise = new Promise((resolve, reject) => {
function handleMessage(event) {
timeoutId = setTimeout(() => {
console.log("removeEventListener");
window.removeEventListener("message", handleMessage);
}, timeout);

const messageData = event?.data;
console.log("🚀 ~ handleMessage ~ messageData:", messageData);

if (messageData?.type !== returnType) {
return;
}

if (messageData && messageData.type === returnType) {
resolve(messageData);
} else {
reject(new Error("No data received in message"));
}

clearTimeout(timeoutId);
window.removeEventListener("message", handleMessage);
}

window.addEventListener("message", handleMessage);
});

return await Promise.race([responsePromise, timeoutPromise]);
}

document
.querySelector("#btns")
.addEventListener("click", async (event) => {
// 检测安装及Google 可用性
if (event.target.matches(".install")) {
waitForPostMessage({
type: "GLARITY_PING_URL",
timeout: 2000,
})
.then((data) => {
console.log("Received message data:", data?.data);
})
.catch((error) => {
console.error("Failed to receive message:", error);
});
}
});
</script>
</body>
</html>

Chrome 扩展接收并发送消息

content-script.js

// content-script.js
window.addEventListener("message", async (message) => {
const messageData = message.data || {};

const { type, data = {} } = messageData;

switch (type) {
case "GLARITY_PING_URL": {
const res = await Browser.runtime.sendMessage({
type: "PING_URL",
data: data,
});

window.postMessage({ type: "RETURN_GLARITY_PING_URL", data: res });

break;
}

default:
break;
}
});

background.js

// background.js
chrome.runtime.onMessage.addListener((request, sender) => {
if (request.type === "PING_URL") {
const { url = "https://google.com/", timeout } = request.data || {};

return fetch(url)
.then((res) => {
return { ok: res?.ok };
})
.catch(() => {
return { ok: false };
});
}
});

转载请注明出处: https://blog.givebest.cn/javascript/2024/06/14/web-page-using-postmessage-to-communicate-with-chrome-extension.html