Abdul Kadir
Abdul Kadir

Reputation: 69

Wait loop to finish first - Typescript (Angular)

So I have this code here triggered using click on HTML page:

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 problem is, I tried to catch the length of this.warningNameList variable. But it always shows "0" on the result.

I know the problem is because this should be work in asynchronously. But I don't know how to apply it in typescript. Been search this case but I always failed to apply. Anyone can help me out?

I already put await inside the loop, but seems it's not working because of wrong placement.

Some reference that I found out there is this => JavaScript async and await in loops

Thanks in advance

Upvotes: 0

Views: 391

Answers (1)

Indrajeet
Indrajeet

Reputation: 501

Putting await inside loop is not gonna help you. as it is running in a different context already.

What you need to do is probably chain this 2 operations one after another after using promise instead of observable here.

you can probably do 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();
          }
        }
      );
    }
  }

Just like above code convert observables to promise, don't subscribe them. This way you can use async await syntax with obervables as well, although find out how to handle errors this way.

Upvotes: 1

Related Questions