В последнее время я создаю расширение Chrome, которое начинается (с внутри фонового скрипта) с вызова API. Затем результаты API передаются в скрипт контента, который будет l oop через результаты API. Однако между скриптами содержимого l oop для повторного вызова API потребуется второй вызов фонового сценария. Затем, когда скрипт контента завершит свою работу, он отправит ответ обратно в фоновый режим, сообщив ему, следует ли продолжить с дополнительными вызовами API или остановить.
Проблема, с которой я столкнулся, связана с асинхронной передачей сообщений в между сценарием содержимого и фоновым сценарием. В частности, ошибка the message port closed before a response was received
появляется как в фоновой, так и в контентной консолях. Я просматривал документы chrome и другие сообщения stackoverflow, и хотя я добавил return true
, чтобы указать, что это будет асинхронно, порты сообщений все еще закрыты для меня. Было бы лучше использовать длительное соединение, чтобы держать порты открытыми? Я также включил упрощенную версию только с передачей сообщений.
background.ts
/* global chrome */
import "chrome-extension-async";
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
if (request.msg === "start") sendMessageToContentScript();
else if (request.msg === "content message #1") {
console.log("message from content script");
let results = await secondAPICall();
sendResponse({ results });
}
return true;
});
const getCurrentTab = async () => {
const tabs = await chrome.tabs.query({ active: true });
return tabs[0];
};
const sendMessageToContentScript = async () => {
const currentTab = await getCurrentTab();
await chrome.tabs.sendMessage(currentTab.id, {
parameter: "background message #1",
});
};
const secondAPICall = async () => {
let result = await testTimeout();
console.log("result:", result);
console.log("now send results back to content");
};
async function testTimeout() {
await timeout(3000);
return { x: 100, y: 200 };
}
function timeout(ms: any) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
content.ts
/* global chrome */
import "chrome-extension-async";
const onMessage = async (request: any, sender: any, sendResponse: any) => {
console.log("now async message back to background");
let asyncResults: any = await asyncCallToBackground();
console.log("asyncResults:", asyncResults); // returned as UNDEFINED
console.log("loop continues...");
// sendResponse();
return true;
};
/**
* @returns async results from background script
*/
async function asyncCallToBackground() {
await chrome.runtime.sendMessage(
{ msg: "content message #1" },
async (response) => {
let results = await response;
return results;
}
);
}
chrome.runtime.onMessage.addListener(onMessage);