What could be causing the code to not wait for the listener to finish its execution?

I've been attempting to make sure that the listener has processed all messages before proceeding with console.log("Done") using await, but it doesn't seem to be working. What could I possibly be overlooking?

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: The inspiration behind my approach comes from this answer

Answer №1

const myFunction = (element, index) => {
  return new Promise(async (resolve) => {
    element.scrollIntoView();
    element.children[0].click();
    console.log('Button clicked for', element);

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

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

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

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

(async () => {
  await myFunction(element0, 0);
  console.log("Task completed");
})();

Give it a try!

Answer №2

Due to the asynchronous nature of the port.onMessage.addListener function, the code does not wait for the listener to complete before executing the console.log("Done") statement. This results in the listener not processing all messages before moving on.

To remedy this issue and ensure that the code waits for the listener to finish processing, you can enclose the listener in a Promise and utilize the await keyword to hold off execution until the Promise resolves. Below is an updated snippet 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 triggered
    };
    const port = Browser.runtime.connect();
    port.onMessage.addListener(listener);

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

  await listenerPromise; // Ensure code waits for Promise resolution

  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");

This revised version encapsulates the listener within a Promise, where resolve() is invoked within the listener to indicate Promise fulfillment. By utilizing await, the code halts until the Promise is resolved prior to proceeding to console.log("Done").

Kindly note that the functionality relies on the correct operation of the Browser.runtime.connect() and port.postMessage() functions. It is essential to have the necessary setup and configurations in place for these functions to operate as intended.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The styles from the npm package are not being properly applied to the class

After creating my react npm package using webpack, I encountered an issue where the styles from the package were not being applied to classes when installed in my react project. I used style-loader in my webpack configuration, but kept getting errors sayin ...

React Native formInput Component with Underline Decoration

Utilizing the FormInput element in React Native Elements, I have observed a line underneath each FormInput component. Interestingly, one line appears fainter than the other. This is how the form looks: <View style={styles.container}> ...

Unable to dynamically populate Bootstrap select with real-time search and multiple options using jQuery

How can I dynamically populate a select statement with options retrieved from PHP code? <select name='friends[]' id='friends' class='selectpicker show-tick form-control' data-live- search='true' multiple& ...

Retrieving images from a server via AJAX requests

As I delve into learning AJAX, I encountered an issue with retrieving an image from my WAMPSERVER www.directory. Within the IMAGES file, there is an image titled logo.png that I'm attempting to access using the following code: function loadXMLDoc() { ...

Is it possible for search engines to crawl and index specific pages within a web application that is powered by

I have created a web application with a dynamic JavaScript interface that communicates with the server through AJAX requests. The content of the page is determined by the data after the hashtag in the URL, which is fetched from the server and displayed acc ...

Creating a collapsing drop down menu with CSS

I utilized a code snippet that I found on the following website: Modifications were made to the code as shown below: <div class="col-md-12"> ... </div> However, after rearranging the form tag, the drop-down menu collapse ...

Do you notice a discrepancy in the number returned by Javascript's Date.getUTCDate() when the time component is set to

Consider the following code snippet: const d = new Date('2010-10-20'); console.log(d.getUTCDate()); If you run this, the console will output 20. However, if you modify the code like so: const d = new Date('2010-10-20'); d.setHours(0, ...

Upgrading from Angular 2 to 4 causes compilation failure in project

Recently, I upgraded my Angular project from version 2 to version 4. The steps I followed for this upgrade are as follows: 1- Deleted the /node_modules/ folder 2- Executed the following command: npm install @angular/common@latest @angular/compiler@lat ...

Auto play feature malfunctioning in Onsen-UI Carousel attribute settings

When utilizing onsen UI in my mobile web application, I encountered an issue with the autoplay property not functioning properly within the carousel. <ons-page> <ons-toolbar> <div class="left"> <ons-toolbar-button on ...

Keep things in line with async functions in Node JS

Hello, I am just starting out with NodeJs and I have a question. I am trying to push elements into an array called files based on the order of the urls provided, but it seems like I'm getting a random order instead. Below is the code I've been wo ...

I'm facing a frustrating issue where using NodeJS with the Passport local strategy is resulting

I am experiencing a severe headache when attempting to log in using Passport. When I make a post request to /login with an email and password, Passport successfully authenticates it without any errors. However, the return res.redirect('/user') fu ...

Vue.js HTML5 Editor_vueful

I am currently utilizing browserify and attempting to incorporate the vue-html5-editor library from https://github.com/PeakTai/vue-html5-editor. However, when I attempt the following code: Vue.use(require('vue-html5-editor')); An error is thro ...

specialized html elements within data-ng-options

I have a code snippet where I am populating select options from a controller using data-ng-options. However, I would also like to include an icon with each option. For example, I want to append <span class="fa fa-plus"></span> at the end of e ...

jQuery menu fails to toggle the class name

The toggle functionality in the Menu is not working properly. Upon clicking the toggle button, I encountered the following JavaScript error: "message": "Uncaught TypeError: Cannot read property 'toggle' of undefined", "filename": "https://st ...

Stop procrastinating and take action before the JavaScript function concludes

Currently, I am experimenting with onkeydown events to capture the input value in a textarea, process it through a PHP file using Ajax post method, and display the result in an external div. However, the issue is that whenever a key is pressed, I am unable ...

Leveraging the outcome of a for loop in order to set a condition within an else if statement

How can I condition my third else if statement based on the result of a for loop? //If player clicks centre on first move go in corner square if (current[4] === playerToken && this.state.stepNumber === 1) { let move = c ...

In order to set a condition for the mat date picker to display a text box in Angular if the selected date is for someone under 18 years old

I need assistance with displaying a text field based on age validation. The requirement is to show the input field only if the age is less than 18. Below is the code snippet I am currently working with: <form [formGroup]="form"> ...

What is the best way to remove table row data fetched from an API within a table?

Can someone assist me with deleting the table tr from the user table, where data is retrieved from an API? I have attempted the code below: $("principleTable").find("tr").hide(); $("#delAgentModal").modal("hide"); ...

What is the best way to insert a placeholder React element into a different Component using TypeScript?

I've encountered a Typescript error that has me stumped. Check out the code snippet below: interface AppProps { Component: JSX.ElementClass; pageProps: JSX.ElementAttributesProperty; } const App = ({ Component, pageProps }: AppProps) => { co ...

What is the best approach to determine the value of a textbox in an array for each row of

I am trying to display the total sum of values for each row in a data array. There are 5 rows of data, and I need to calculate the results for each one. Can someone assist me in solving this? function calculateTotalValue(){ var total = (document.get ...