Search code examples
javascriptgoogle-chrome-extensionasync-awaitgoogle-chrome-devtools

Chrome async wait sending content before request completed


Below is an attempt to extract some information from a webpage and then display it on a Chrome extension page.

The problem I have based on many hours of research seems to be that the sending of variable extracted from webpage to extension page failed as my extractor is asynchronous.

The variable that arrives at my extension page after the last step below is [object object].

It seems that the sendMessage action doesn't wait for async-wait step to finish before sending results to the receiving end. I have tried many fixes from Stack Overflow answers, but I just don't seem to find a solution.

1.) This code will run on the webpage to extract some information (the async await is needed in original code, and the below is just a sample).

async function Extractor(document) {
    var item = document.getElementbyId("....");
    await new Promise(r => setTimeout(r, 3000));

    return item
}

2.) I assume this code sends the message to the one below telling it to run and retrieve extractor results.

chrome.runtime.sendMessage({
    action: "getSource",
    source: Extractor(document)
});

3.) This code is in popup.js, where my intention is to insert the extractor's result from webpage into a popup.html extension page, under node id = "message".

chrome.runtime.onMessage.addListener(function(request, sender) {
   if (request.action == "getSource") {
      message.innerText = request.source;
   }
});

Solution

  • This sample displays document.title in a popup.

    File popup.js

    const message = document.getElementById("message");
    
    chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
      chrome.scripting.executeScript({
        target: { tabId: tabs[0].id },
        function: getDocumentTitle
      });
    });
    
    async function getDocumentTitle() {
      chrome.runtime.sendMessage({
        action: "getSource",
        source: await Extractor()
      });
    
      async function Extractor() {
        var item = document.title;
        await new Promise(r => setTimeout(r, 3000));
    
        return item;
      }
    }
    
    chrome.runtime.onMessage.addListener(function (request, sender) {
      if (request.action == "getSource") {
        message.innerText = request.source;
      }
    });
    

    File manifest.json

    {
      "name": "getDocumentTitle",
      "version": "1.0",
      "manifest_version": 3,
      "permissions": [
        "scripting"
      ],
      "host_permissions": [
        "<all_urls>"
      ],
      "action": {
        "default_popup": "popup.html"
      }
    }
    

    File popup.html

    <!DOCTYPE html>
    <html>
    
    <body>
      <div id="message"></div>
      <script src="popup.js"></script>
    </body>
    
    </html>