Waiting for the execution of the loop to be completed before proceeding - Typescript (Angular)

There's a code snippet triggered on an HTML page when clicked:

public salaryConfirmation() {
    const matDialogConfig: MatDialogConfig = _.cloneDeep(GajiIdSettings.DIALOG_CONFIG);
    this.warningNameList = [];

    for(let i=0; i < this.kelolaDataPenggajianInfoDataKaryawanList.length; i++) {
      const positionClassId = this.selectedKaryawanAllData[i].position.positionClass.id;
      const beginYearMonth = this.inputForm.get('bulanBerlaku').value;
      const gajiPokok = this.kelolaDataPenggajianInfoDataKaryawanList[i].gaji;

      this.structureAndSalaryScaleValidationService.getSalaryRange(positionClassId, beginYearMonth, gajiPokok)
        .pipe(takeUntil(this.ngUnsubscribe))
        .subscribe(
          async (result) => {
            this.uiBlockService.hideUiBlock();
            if(result.status == 'warning') {
              if(result.warnings[0].code == 'trxMutasiKaryawan.confirmation.alert') {
                await this.warningNameList.push(this.kelolaDataPenggajianInfoDataKaryawanList[i]);
              }
            }
          },
          (error) => {
            this.uiBlockService.hideUiBlock();
            this.contentAlertService.error(error.errors);
          },
          () => { this.uiBlockService.hideUiBlock(); }
        )
    }

    matDialogConfig.data = this.warningNameList;
    console.log("this.warningNameList.length :", this.warningNameList.length);

    if (this.warningNameList.length > 0) {
      this.save();
    } else {
      this.inputMassalGajiWarningComponentDialogRef = this.dialog.open(InputMassalGajiWarningComponent, matDialogConfig);
      this.inputMassalGajiWarningComponentDialogRef.afterClosed().subscribe(
        (confirm: boolean) => {
          if (confirm) {
            this.save();
          }
        }
      );
    }
  }

The issue is that the length of the this.warningNameList variable always shows as "0" in the result.

I understand that this should work asynchronously, but I'm unsure how to implement it in TypeScript. I've tried placing await inside the loop, but it doesn't seem to work due to incorrect placement.

I came across a reference regarding JavaScript async and await in loops while researching this issue.

Any help on this matter would be greatly appreciated. Thank you!

Answer №1

Placing await within a loop will not be beneficial as it is already running in a separate context.

What you should do is likely chain these two operations one after the other using promises instead of observables here.

You can try something like this,

public async salaryConfirmation() {
    const matDialogConfig: MatDialogConfig = _.cloneDeep(GajiIdSettings.DIALOG_CONFIG);
    this.warningNameList = [];

    for(let i=0; i < this.kelolaDataPenggajianInfoDataKaryawanList.length; i++) {
      const positionClassId = this.selectedKaryawanAllData[i].position.positionClass.id;
      const beginYearMonth = this.inputForm.get('bulanBerlaku').value;
      const gajiPokok = this.kelolaDataPenggajianInfoDataKaryawanList[i].gaji;

      let result = await this.structureAndSalaryScaleValidationService.getSalaryRange(positionClassId, beginYearMonth, gajiPokok)
        .pipe(takeUntil(this.ngUnsubscribe)).toPromise();

      // Transform following data
      // .subscribe(
      //    async (result) => {
      //      this.uiBlockService.hideUiBlock();
      //      if(result.status == 'warning') {
      //        if(result.warnings[0].code == 'trxMutasiKaryawan.confirmation.alert') {
      //          await this.warningNameList.push(this.kelolaDataPenggajianInfoDataKaryawanList[i]);
      //        }
      //      }
      //    },
      //    (error) => {
      //      this.uiBlockService.hideUiBlock();
      //      this.contentAlertService.error(error.errors);
      //    },
      //    () => { this.uiBlockService.hideUiBlock(); }
      //  )
    }

    matDialogConfig.data = this.warningNameList;
    console.log("this.warningNameList.length :", this.warningNameList.length);

    if (this.warningNameList.length > 0) {
      this.save();
    } else {
      this.inputMassalGajiWarningComponentDialogRef = this.dialog.open(InputMassalGajiWarningComponent, matDialogConfig);
      this.inputMassalGajiWarningComponentDialogRef.afterClosed().subscribe(
        (confirm: boolean) => {
          if (confirm) {
            this.save();
          }
        }
      );
    }
  }

Similar to the code above, convert observables to promises instead of subscribing to them. This way, you can use the async-await syntax with observables as well, although figure out how to handle errors using this method.

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

Building a Dynamic Web App with PHP and Vue.js

I developed an API using PHP and you can access it through this link: However, I encountered an issue when trying to display the data on the front-end of my Vue.js (Home.vue) file using axios. Below is the code I used: <ul class="ta-track-list" v-if= ...

NX nest application: accessing environment variables from the distribution directory

I've organized my project structure like this: https://i.sstatic.net/WRKCI.png Using nx with nest. In the app.module.ts file, I've set up the ConfigModule to read the .env file based on the NODE_ENV variable, which is then used to connect to Mo ...

Creating a Custom "Save As" Dialog in HTML5 and JavaScript for Downloading Files

I have developed a NodeJS/Express application that is capable of generating and downloading an Excel document (created using ExcelJS) when a user clicks on a button. Currently, the file gets automatically downloaded to the default download location of the ...

Exploring the combined application of the AND and OR operators in JavaScript programming

{Object.keys(groupByMonthApplicants).map((obj,i) => <div key={obj} style={(i > 0 && (this.state.selectedTabId !== 'rejected' || this.state.selectedTabId !== 'approved')) ? {paddingTop:'15px',background:&a ...

Utilizing a personalized directive within a ionic popup

I am currently using the ion-textarea autosize directive: import { Directive, HostListener, ElementRef } from '@angular/core'; @Directive({ selector: 'ion-textarea[autosize]' }) export class AutoResizeTextareaDirective { readonly ...

Leveraging npm packages within a Meteor project through cosmos:browserify

Trying to implement Radium, a JavaScript library for inline CSS, by following the instructions located here. In my app.browserify.js file: Radium = require("radium"); Within package.json: "radium": "0.13.4" Upon attempting to utilize Radium in the app&a ...

Using ngTable within an AngularJS application

While working on my angularjs application, I encountered an issue with ngtable during the grunt build process. It seems that the references are missing, resulting in the following error: Uncaught Error: [$injector:modulerr] Failed to instantiate module pa ...

Cypress fails to log requests in the Command Log

I'm having trouble intercepting requests to the Backend using Cypress. Strangely, I can't see some of the XHR requests in the DevTools, even though they are there. To help illustrate the issue, I've included a screenshot with arrows. https:/ ...

A guide on transforming Jonatas Walker's TimePicker into a custom JavaScript class or a versatile jQuery plugin

I came across a timepicker solution on this Stack Overflow answer that I really liked. However, I encountered difficulties trying to implement it in a project where input elements are dynamically created. It seemed like the timepicker required specific han ...

The function record.factory does not exist

Here is the code for the AppComponent: import { Component, OnInit } from '@angular/core'; import { APICommunicationService } from './api-comm/api-communication.service'; import { Observer } from 'rxjs'; @Component({ sel ...

AngularJS attempting to conceal the popup menu upon clicking outside of the designated area

My HTML structure looks like this: <div> <a href="" ng-click="$scope.show_menu = !$scope.show_menu">Options</a> <div class="options_box" ng-show="$scope.show_menu"> <button>Option1</button> ... ...

Struggling to fetch data from the Strapi page is posing a challenge

Currently, I am facing an issue where the frontend developers on my team are unable to retrieve data from the backend that I built for them using Strapi. Even after pulling my changes from github, they continue to face difficulties accessing the data. The ...

Enhance user experience with dynamic color changes in JavaScript

Looking to create a navigation menu with unique colors for each selected state? Check out the code below! After searching extensively, I stumbled upon this snippet. While it only includes one selected state, you can easily customize it for three different ...

Does PHP/AJAX only function when an output is generated?

I am attempting to fetch the Wordpress blog header into a php file in order to use it for an AJAX call function. define('WP_USE_THEMES',false); echo 'Something'; require(explode("wp-content",realpath(dirname(__FILE__)))[0].'wp-b ...

Challenges with Initializing Angular 2 Router

I'm encountering a problem with the Angular 2 Router. My goal is to navigate through my application using a function that utilizes the navigate function from the Router, similar to how it's done in the official example. Here's what I curren ...

Adjust index starting from 0 in JavaScript

Struggling with setting a consistently unique index that increments by one. Here is an example of my array: const originalArr = [ { name: 'first parent array', childArray: [ { name: '1 / first child' }, ...

Can this pagination task be accomplished without the use of backgrid?

I have been exploring ways to implement server-side pagination similar to what Datatables offers, and during my search I came across the backbone.paginator library on GitHub. However, I am curious if there are any other options available as well. After ex ...

Update an array while monitoring for a specific event

Working with Ionic, my goal is to push an array of an object when a specific event is emitted. This is what I currently have: export class PublicationService { constructor(private storage: Storage) {} private addPublicationSubject = new Be ...

Angular displaying undefined for service

I have created a service for uploading images to a server, and I am encountering an issue when calling this service from my controller. The error message indicates that the function 'uploadFileToUrl' is undefined. Below is the code for my servic ...

In jQuery, there seems to be an issue where the click event is not functioning properly on an element that has been

I am using jQuery to append items, but I am having trouble binding events to the appended items. My appending code looks like this: var item = '<div id="'+newInputId+'" class="col-md-9" style="padding-right: 0px; ...