Why is the code not waiting for the listener to complete?

101 Views Asked by At

I am trying to wait for the listener to listen to all messages before moving on to console.log("Done") using await but it is not happening. What am I missing.

const f = async (leftPaneRowEle,index) => {
    leftPaneRowEle.scrollIntoView()
    leftPaneRowEle.children[0].click()
    console.log('downloadBtn clicked for', leftPaneRowEle)

    const listener = (msg: any) => {
      console.log('frontend msg:', msg)
    }
    const port = Browser.runtime.connect()
    port.onMessage.addListener(async (msg, sender) => {
      console.log("BG page received message", msg, "from", sender);
      listener(msg)
    });
    await port.postMessage({ question: "Can you " + allTFBs[leftpaneindexes[index]] + ":" + desc })
    return async () => {
      await port.onMessage.removeListener(listener)
      await port.disconnect()
    }
}

const en: HTMLElement = document.querySelectorAll('#extensionListTable tbody')[0] as HTMLElement
const leftPaneRowEle0 = en.children[leftpaneindexes[0]]
await f(leftPaneRowEle0,0)
console.log("Done")

PS: My approach is inspired by this answer

2

There are 2 best solutions below

9
Stefan On
const f = (leftPaneRowEle, index) => {
  return new Promise(async (resolve) => {
    leftPaneRowEle.scrollIntoView();
    leftPaneRowEle.children[0].click();
    console.log('downloadBtn clicked for', leftPaneRowEle);

    const listener = (msg) => {
      console.log('frontend msg:', msg);
    };
    const port = Browser.runtime.connect();
    
    port.onMessage.addListener((msg, sender) => {
      console.log("BG page received message", msg, "from", sender);
      listener(msg);
    });

    port.onDisconnect.addListener(() => {
      console.log("Port disconnected");
      resolve(); // Resolve the Promise when the port disconnects
    });

    await port.postMessage({ question: "Can you " + allTFBs[leftpaneindexes[index]] + ":" + desc });
  });
};

const en = document.querySelectorAll('#extensionListTable tbody')[0] as HTMLElement;
const leftPaneRowEle0 = en.children[leftpaneindexes[0]];

(async () => {
  await f(leftPaneRowEle0, 0);
  console.log("Done");
})();

Try this

1
Stalin Alvarado On

The code is not waiting for the listener to complete because the port.onMessage.addListener function is asynchronous and does not block the execution of subsequent code. Therefore, the console.log("Done") statement is executed before the listener has a chance to process all the messages.

To ensure that the code waits for the listener to complete before moving on, you can wrap the listener in a Promise and use await to wait for the Promise to resolve. Here's an updated version of the code:

const f = async (leftPaneRowEle, index) => {
  leftPaneRowEle.scrollIntoView();
  leftPaneRowEle.children[0].click();
  console.log('downloadBtn clicked for', leftPaneRowEle);

  const listenerPromise = new Promise((resolve) => {
    const listener = (msg) => {
      console.log('frontend msg:', msg);
      resolve(); // Resolve the Promise when the listener is called
    };
    const port = Browser.runtime.connect();
    port.onMessage.addListener(listener);

    port.postMessage({ question: "Can you " + allTFBs[leftpaneindexes[index]] + ":" + desc });
  });

  await listenerPromise; // Wait for the Promise to resolve

  return async () => {
    port.onMessage.removeListener(listener);
    port.disconnect();
  };
};

const en: HTMLElement = document.querySelectorAll('#extensionListTable tbody')[0] as HTMLElement;
const leftPaneRowEle0 = en.children[leftpaneindexes[0]];

await f(leftPaneRowEle0, 0);
console.log("Done");

In this updated code, the listener is wrapped in a Promise, and the resolve() function is called inside the listener to mark the Promise as resolved. Then, using await , the code waits for the Promise to resolve before moving on to console.log("Done") .

Please note that this code assumes that the Browser.runtime.connect() and port.postMessage() functions work as expected. Make sure you have the necessary setup and configurations in place for those functions to function correctly.