Executing the Angular 2 foreach loop before the array is modified by another function

Currently, I am facing some difficulties with an array that requires alteration and re-use within a foreach loop. Below is a snippet of the code:

this.selectedDepartementen.forEach(element => {
      this.DepID = element.ID;
      if (this.USERSDepIDs.indexOf(this.DepID) == -1) {
        this.insertDepartementCoupling(this.DepID, this.USERid, this.AJID, res => {
          if (res) {
            this.loading = false;
            return;
          }
          this.removeAllFromArray(this.USERSDepIDs, this.DepID, res => {
            this.USERSDepIDs = res;
          })
        })
      } else
      {
        this.updateDepartementCoupling(this.DepID, this.USERid, this.AJID, res => {
          if (res) {
            this.loading = false;
            return;
          }
          this.removeAllFromArray(this.USERSDepIDs, this.DepID, res => {
            this.USERSDepIDs = res;
          })
        })
      }
    });

The issue here is that when the function removeAllFromArray is called to remove the last used DepID, the foreach loop does not wait for it and continues to execute. It seems like an asynchronous problem, so any suggestions on how to address this would be greatly appreciated.

Thank you in advance!

EDIT

Included is the function insertDepartementCoupling requested by user Duncan.

async insertDepartementCoupling(DepID, USERid, AJID, callback) {
    var test = await this.departementService.insertDepartementCoupling(DepID, USERid, AJID).subscribe(
      data => this.mockdata = data,
      error => {
        this.showMessage("error", "Departement koppeling niet gelukt!", "Departement koppeling niet gelukt, zie console voor meer informatie.");
        callback(true);
      },
      () => {
        if (this.mockdata._body) {
          this.showMessage("error", "Departement koppeling niet gelukt!", "Contacteer de administrator!");
          callback(true);
        } else {
          this.showMessage("succes", "Departement koppeling geslaagd!", "Gebruiker is gekoppeld aan de departement(en).");
          callback(false);
        }
      });
  }

Answer №1

In order to modify the functions insertDepartmentCoupling, updateDepartementCoupling, and possibly removeAllFromArray to be asynchronous using Promises instead of callbacks, you can rewrite your code like this:

for (const element of this.selectedDepartementen) {
    this.DepID = element.ID;
    if (this.USERSDepIDs.indexOf(this.DepID) == -1) {
        if (await this.insertDepartementCoupling(this.DepID, this.USERid, this.AJID)) {
            this.loading = false;
        } else {
            this.USERSDepIDs = await this.removeAllFromArray(this.USERSDepIDs, this.DepID);
        }
    } else {
        if (await this.updateDepartementCoupling(this.DepID, this.USERid, this.AJID)) {
            this.loading = false;
        } else {
            this.USERSDepIDs = await this.removeAllFromArray(this.USERSDepIDs, this.DepID);
        }
    }
}

With TypeScript, you can use the for..of loop for iterating arrays instead of forEach, which can help avoid additional callback functions.

This updated code ensures that each iteration inside the for loop will wait for completion before moving on, making the entire process fully asynchronous. The containing function must be declared as async and return a Promise which can be handled with await or .then().

The insertDepartementCoupling function is already asynchronous and uses an observer internally. To convert it to return a Promise instead of a callback, you can simply use the toPromise() method on the observable. This Promise will resolve with the last data value, allowing you to handle the boolean result accordingly:

async insertDepartementCoupling(DepID, USERid, AJID): Promise<boolean> {
    let result = false;
    await this.departementService.insertDepartementCoupling(DepID, USERid, AJID).subscribe(
      data => this.mockdata = data,
      error => {
        this.showMessage("error", "Failed to couple department!", "Department coupling failed, check console for more information.");
        result = true;
      },
      () => {
        if (this.mockdata._body) {
          this.showMessage("error", "Failed to couple department!", "Contact administrator!");
          result = true;
        } else {
          this.showMessage("success", "Department coupling successful!", "User has been linked to department(s).");
          result = false;
        }
      }).toPromise();
     return result;
  }

Alternatively, you can convert the Observable to a Promise earlier in the function and simplify the logic without the need for an intermediate variable:

async insertDepartementCoupling(DepID, USERid, AJID): Promise<boolean> {
    return this.departementService.insertDepartementCoupling(DepID, USERid, AJID).toPromise()
    .then(
      data => {
        this.mockdata = data
        if (this.mockdata._body) {
          this.showMessage("error", "Failed to couple department!", "Contact administrator!");
          return true;
        } else {
          this.showMessage("success", "Department coupling successful!", "User has been linked to department(s).");
          return false;
        }
      },
      error => {
        this.showMessage("error", "Failed to couple department!", "Department coupling failed, check console for more information.");
        return true;
      });
  }

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

What is the process for implementing pagination in vue-tables-2 with a Laravel REST API?

I'm looking to implement pagination on Vue server-table using a Laravel endpoint. How can I achieve this? Below is my component setup: <template> <div> <v-server-table :columns="columns" url="/object/find" :options="option ...

Can an Angular 9 application access an uploaded file through an HTTP request from the $_FILES array?

I'm currently facing an issue when attempting to send a file to a PHP server using an HTTP request in Angular 9. The problem lies in the fact that the server is not able to receive the uploaded file in $_FILES. Below is the code snippet I have written ...

How to efficiently import Xlsx and csv files using AngularJS

I am looking for a way to extract data in json format from each line of xlsx and csv files using AngularJS. Currently, I am utilizing the angular-file-upload library to access the file as shown below: $scope.LatLongUploader = new FileUploader({ //url ...

Are there any web browsers that automatically switch to a non-SSL connection if an attempt to connect with SSL

I regularly utilize jQuery along with jQuery.ajax to make connections between pages. I am interested in establishing a connection from a non-SSL page to an SSL page using ajax. Are there any web browsers that will attempt to connect via non-SSL if the con ...

What is the best approach to extracting tightly-coupled code and converting it into an external library?

I have a question regarding paradigms that I would like to address, and if this is not the appropriate platform, please guide me to the right place. Your recommendations are most welcome :) Currently, I am tasked with extracting a significant piece of fun ...

Exploring the functionality of ngTemplateOutlet, the implementation of @ContentChild, and the benefits of using ng

Lately, I've been dedicating more time to grasp the concepts presented in the blog post titled Creating Reusable Components with NgTemplateOutlet in Angular If you want to see the code in action, it's available on stackblitz. Within the UsageEx ...

"Partially loaded" when document is ready

Is there a way for me to trigger a function once the element identified by #container has finished loading in the DOM? Instead of waiting for the entire DOM to load using document.ready(), I'd like to start populating #container right after it's ...

Next.js application shows 404 errors when trying to access assets within the public directory

I've been struggling to display the favicon for my site (which uses next.js). Despite going through numerous Stack Overflow posts and tutorials, I'm feeling increasingly frustrated. The structure of my project, particularly the public directory, ...

When the drawer is opened, there is a strange phenomenon of all buttons being mysteriously clicked

Currently, I am working on a single-page web application utilizing React and Material UI, along with React-Mini-Router for routing. The app features a side drawer that is activated by clicking a hamburger icon located in the top app bar. Each item in the d ...

Facing issues with Angular2 integration with Semantic UI

I am currently working with Angular2 and Nodejs. Within my application, I have a list of employees that includes their names, addresses, ranks, and other details. My goal is to display additional information when a user hovers over an employee's name. ...

What is the best way to utilize the useSWR hook when there are necessary logical operations to be performed on the response before proceeding with the next API call

I am currently utilizing the swr library in a Create React App and require the usage of the useSWR hook for data fetching that is both contingent and conditional. The specific task at hand involves: Making an API call to retrieve an id which will be used ...

I'm having trouble getting my button to work with addEventListener while using Ejs and Express. What could

Creating a Twitter-like platform where I can post tweets and have them display on the same page has been quite challenging. I've set up each post to have an Edit button initially hidden with 'display:none'. However, when I try to click on th ...

What is the best way to trigger the Javascript blur event following a click event that results in the element losing focus

Encountering this issue multiple times has left me dissatisfied with the solutions I've implemented in the past. The challenge lies in dealing with an input box that triggers a validation process on blur, while also having a button that populates the ...

I'm currently experiencing a challenge with a project I'm tackling that specifically deals with chart.js

In my recent coding project, I created a script to gather user input and then present it in various chart formats. However, upon executing the code, the selected chart fails to display after inputting values and clicking on the "generate chart" button. Her ...

Retrieve the weekday dates for a specific year, month, and relative week number using Javascript or Typescript

I am in need of a custom function called getDaysOfWeekDates that can take a year, a month (ranging from 0 to 11), and the week number of each month (usually 4-5 weeks per month) as parameters, and return a list of dates containing each day of that particul ...

Using JavaScript in Django templates: Displaying errors with a JavaScript function

Update: I recently made changes to my code, and it now looks like this: <script> function updateFunction(calibrationId) { document.getElementById(calibrationId).innerHTML = "<ul><li>" + calibrationId + "</li>" ...

Stop hyperlinks from automatically opening in a new tab or window

I'm having trouble with my website links opening in new tabs. Even after changing the attributes to _self, it still doesn't work. Can someone please review my code below and provide a solution? Feel free to ask for more clarification if needed. ...

Efficient method of delivering cohesive information from database to user without the need for continuous querying

Within the database, there is stored data about each user that typically remains constant. However, occasionally a user may update their information, such as changing their name. This data includes the user's name, username, and company details. The ...

The issue with the $(window).width() property not functioning correctly in Internet Explorer

Currently, I have a Div element with absolute positioning: <div id="target" style="height: 300px; position: absolute; top: 275px;"></div> My goal is to calculate the horizontal resolution of the screen using JavaScript. With this width, I the ...

The componentWillUnmount method is not being called

I'm currently working on a Backbone application and I'm in the process of integrating React components. The React component is being mounted using the following code: ReactDOM.render( <WrappedComponent />, node ); where "node" represents ...