Как я могу передать НЕСКОЛЬКО асинхронных сообщений между фоновым скриптом и скриптом контента? - PullRequest
0 голосов
/ 13 апреля 2020

В последнее время я создаю расширение 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);
...