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

Leverage the power of Angular to seamlessly integrate jQuery code across your

Interested in incorporating the plugin into my AngularJS project. To achieve this, I have to: $(document).ready( function() { $("html").niceScroll(); } ); The challenge is figuring out where to place this code so that it runs site-wide and ...

Is there a way to easily identify the error in my Express application that is preventing my hbs template from running properly?

I am facing an issue with my express code where it is not rendering the data properly. Can someone please assist me in resolving this error? Your help will be greatly appreciated! let express=require('express'); let app=express(); ...

Is there a way for me to generate a tab that shows content when hovered over?

Is it possible to create a tab that displays a vertical list of redirections when the mouse hovers over it, and hides when the mouse is moved away? This seems like a challenging task. Can someone guide me on how to achieve this, especially if it involves ...

The disappearance of the overlay background due to modal reload in NextJS dynamic routing

I am working on a simple NextJS app where clicking on a page opens a modal with updated URL but without triggering a new navigation. The content inside the modal is displayed, while the actual page location is reflected in the URL and refresh takes the use ...

The For loop with varying lengths that exclusively produces small numbers

I'm currently using a for loop that iterates a random number of times: for(var i = 0; i<Math.floor(Math.random()*100); i++){ var num = i } This method seems to be skewed towards producing lower numbers. After running it multiple times, the &apo ...

What could be causing the issue of Vuejs 3.3 defineModel consistently returning undefined?

I am currently working with Nuxt version 3.5.1 and Vuejs version 3.3, however, I am encountering an issue where the defineModel macro always returns undefined. I am unsure why this is happening? <template> <input v-model="count"& ...

Converting JSON HTTP response to an Array in AngularJS 2: A Comprehensive Guide

As I work on a Http get request in Angular 2, the response returned is in JSON format. However, I am facing an issue when trying to use it in a ngFor loop because it is not formatted as an Array. Is there a way to convert JSON data to an Array in Angular ...

Displaying nested data on an Angular 8 table

Hello everyone, I am currently dealing with an HTTP response from a MongoDB and extracting values like: loadOrders(){ this.orderService.getOrders() .subscribe((data:any[])=>{ this.orders=data; } ); } In the orders-li ...

Show the MatCalendar by clicking on a link

Is there a way to trigger the opening of a Material Calendar component using an anchor element? I tried, but the calendar always pops up in the top left corner of the page: <li> <mat-calendar class="hidden"> <input matIn ...

Angular 6 - Resolving the Issue of 'Function calls are not supported in decorators' in Production Builds

Currently, I'm in the process of developing a cutting-edge Angular 6 application. However, as I was progressing with the development phase and tried to create a prod build using the following command: ng build --prod To my dismay, I encountered a pe ...

The promise of returning a number is not compatible with a standalone number

I am currently working on a function that retrieves a number from a promise. The function getActualId is called from chrome.local.storage and returns a promise: function getActualId(){ return new Promise(function (resolve) { chrome.storage.syn ...

Is it possible to create a map of functions that preserves parameter types? How can variadic tuple types in TypeScript v4 potentially enhance this

Initially, I faced a challenge when trying to implement a function similar to mapDispatchToProps in Redux. I struggled with handling an array of functions (action creators) as arguments, but managed to come up with a workaround that works, although it feel ...

Unable to access API hosted on localhost from Angular Client integrated with C# Backend running on a standalone server unit

I have an Angular Client (v14) and a .Net 6 WebAPI running on separate projects within a Raspberry Pi. The setup is for a standalone kiosk where both the front end and backend are hosted on the same device. My goal is to access the front end from a PC on ...

Exploring Elasticsearch: Uncovering search results in any scenario

I've been working on a project where my objective is to receive search engine results under all conditions. Even if I enter a keyword that is not included in the search data or if it is an empty string, I still want to get some kind of result. How can ...

Tips on incorporating a firebase object into your Angular application using $scope

As a beginner in coding, I would greatly appreciate a simple answer. I am attempting to treat a Firebase object as a JavaScript array for use in HTML via $scope. What is the most effective approach? Database: database Current code: var mainApp = angula ...

I am wondering how to use the value assigned to a variable's textContent as an argument for player input in my JavaScript code

i am currently developing a JavaScript project to create a user interface for my rock, paper, scissors game. Currently, the game only runs in the console and prompts the player for input. So far, I have implemented three buttons (one each for rock, paper, ...

Using Angular Directive to create a customized TreeView

Although I am still relatively new to Angular, I need to make some modifications to a treeview directive that I found on NgModules. The existing code looks promising, but I want to customize it to include the ability to add, delete, or modify items. You c ...

Is it best practice to use the AngularFirestoreCollection for updating Firestore items in AngularFire?

Within my application, I have a list that necessitates the use of an "or" condition. However, according to the documentation: "In this case, you should create a separate query for each OR condition and merge the query results in your app." Consequently ...

A guide on parsing a nested JSON file with ExtJS 4

Here is the content of my JSON file named "jobInfo.json": { "job": { "id": 1, "name": "Job 1", "description": "bla bla bla", "locations": { "type": "FeatureCollection", "features": [{ "id": 1, "t ...

Adjust the hue of a specific node

Is there a way to customize the color of an individual node in an eChart treemap? I attempted to set a color property for the node, but it didn't seem to work. While I was able to change the label's color, I'm interested in changing the back ...