0

I have a function which has an API call inside an 'if' condition.When I execute that function, before completing the API response, the program moves to below code lines.That breaks the functional flow since some below codes are running before API response comes Below is my code.

 change(event: any) {

    let selectedUnitIds = event.source.value;
    let newUnitIds = this.getNewUnitIds(selectedUnitIds);

    if (newUnitIds.length !== 0) {
      this.commonServerService.getOrgUnitById(newUnitIds).subscribe(orgUnits => {
        orgUnits.forEach(unit =>
          this.unitMap.set(unit.id, unit)
        );
      });
    }


    //get selected ids' orgunits
    let selectedOrgUnits = this.getSelectedUnits(selectedUnitIds);

    // get tribes of those orgunits
    let need = this.getNeededTribes(selectedOrgUnits);
  }

The problem here is the if condition. If this API is called unconditionally, inside the subscribe method, everything is working asynchronously. Please guide me through this.

later added:- common-server.service.ts

 getOrgUnitById(id: string[]): Observable<Array<OrgUnit>>
  {
    return this.orgUnitService.findOrgUnitByIds(id);
  }
1
  • 1
    can you also post the getOrgUnitById() function from commonServerService? Commented Nov 7, 2019 at 10:28

3 Answers 3

2

You may use 'await' before "this.commonServerService.getOrgUnitById" You will need to declare "change" function as an async

async change(event: any) {

  let selectedUnitIds = event.source.value;
  let newUnitIds = this.getNewUnitIds(selectedUnitIds);

  if (newUnitIds.length !== 0) {
    const orgUnits = await this.commonServerService.getOrgUnitById(newUnitIds);
    orgUnits.forEach(unit =>
      this.unitMap.set(unit.id, unit)
    );
  }

  //get selected ids' orgunits
  let selectedOrgUnits = this.getSelectedUnits(selectedUnitIds);

  // get tribes of those orgunits
  let need = this.getNeededTribes(selectedOrgUnits);
}

async getOrgUnitById(id: string[]): Promise<Observable<OrgUnit[]>>
{
  return await this.orgUnitService.findOrgUnitByIds(id).toPromise();
}
Sign up to request clarification or add additional context in comments.

11 Comments

I tried it but it is said that 'await' has no effect on the type of this expression
You will need to do it in getOrgUnitById too. See updated answer
really is it possible to await for observable?
Probably yes. I suggest to return Promise<Observable<Array<OrgUnit>>>. See updated answer :)
probably not because even if you return promise it's only usable inside subscribe method not the return type. also mixing promise and observable like this is not a good practice.
|
2

You can simply put your code in the response block, it will execute only after completion of API call then, like below -

change(event: any) {

let selectedUnitIds = event.source.value;
let newUnitIds = this.getNewUnitIds(selectedUnitIds);

if (!newUnitIds.length) {
  this.commonServerService.getOrgUnitById(newUnitIds).subscribe(orgUnits => {
    orgUnits.forEach(unit =>
      this.unitMap.set(unit.id, unit)
    );
     this.someAnotherMethod();
  });
} else {
     this.someAnotherMethod();
  }
}

someAnotherMethod() {
  let selectedOrgUnits = this.getSelectedUnits(selectedUnitIds);
  let need = this.getNeededTribes(selectedOrgUnits);
}

3 Comments

that works only if newUnitIds.length is not zero. It doesn't tackle the part newUnitIds.length == 0
I tried to avoid code duplication because it is not an allowed practice in my workplace. :)
@TharushiGeethma good, you can call some global method then. Though no doubt chance of code optimization is always there. :)
0

Use async and await as below code.

To use below code every method call change() method should be async.

 async change(event: any) {

    let selectedUnitIds = event.source.value;
    let newUnitIds = this.getNewUnitIds(selectedUnitIds);

    if (newUnitIds.length !== 0) {
      try{
        await this.getOrgUnitById(newUnitIds);
      }catch (e) {
        console.log(e);
      }
    }
    //get selected ids' orgunits
    let selectedOrgUnits = this.getSelectedUnits(selectedUnitIds);

    // get tribes of those orgunits
    let need = this.getNeededTribes(selectedOrgUnits);
  }


  getOrgUnitById(newUnitIds){
    return new Promise((resolve, reject) => {
      this.commonServerService.getOrgUnitById(newUnitIds).subscribe(orgUnits => {
        orgUnits.forEach(unit =>
          this.unitMap.set(unit.id, unit)
        );
        resolve(orgUnits)
      },error=>{
        reject(error)
      });
    })
  }

2 Comments

It's the same solution than mine. You just use new Promise and kicked off return type on getOrgUnitById
you don't need to create a promise like this you can use toPromise()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.