0

I'm trying to call this function in extractContractsView.

public getInsurantOrBeneficiary(content_type: number, object_id: number) {
    if (content_type == 25) { 
      this.http.get(AppSettings.API_ENDPOINT + '/api/v1/artifical_persons' + "/" + object_id + "/", this.options)
        .map((response: Response) => response.json())
        .subscribe((result: any) => {
          this.data_name = result;
          this.name = this.data_name['name'];
          console.log('Artifical persons' + this.name);
          return this.name;
        });
    } else if (content_type == 12) { 
      this.http.get(AppSettings.API_ENDPOINT + '/api/v1/private_persons' + "/" + object_id + "/", this.options)
        .map((response: Response) => response.json())
        .subscribe((result: any) => {
          this.data_private_persons = result;
          this.id_private_persons = this.data_private_persons['passport_id'];
          console.log('id_private_persons:' + this.id_private_persons);
        });

        this.http.get(AppSettings.API_ENDPOINT + '/api/v1/passports' + "/" + this.id_private_persons + "/", this.options)
        .map((response: Response) => response.json())
        .subscribe((result: any) => {
          this.data_name = result;
          this.name = this.data_name['second_name'] + ' ' + this.data_name['first_name'] + ' ' + this.data_name['paternal_name'];
          console.log('Name in passport:' + this.name);
          return this.name;
        });
    } else if (content_type == 43) { 
      this.http.get(AppSettings.API_ENDPOINT + '/api/v1/sole_proprietorship' + "/" + object_id + "/", this.options)
        .map((response: Response) => response.json())
        .subscribe((result: any) => {
          this.data_name = result;
          this.name = this.data_name['name'];
          console.log('sole_proprietorship' + this.name);
          return this.name;
        });
    }
    return this.name;
  }

The problem is that when I call the getInsurantOrBeneficiary function, I get data only the first iteration. But the content_type [i] and object_id [i] are always different and I expect the function to return a different this.name. I do not quite understand the work with asynchrony and it is possible that this.http.get does not have time to work and I get the answer only once.

 public extractContractsView = (response: Response) => {

    let res = response.json();
    let contracts: ContractsView[] = [];

    for (let i = 0; i < res.length; i++) {

      let insurant = this.getInsurantOrBeneficiary(res[i].insurant_id.content_type, res[i].insurant_id.object_id);
      let beneficiary = this.getInsurantOrBeneficiary(res[i].beneficiary_id.content_type, res[i].beneficiary_id.object_id);

      contracts.push(new ContractsView(
        res[i].id,
        res[i].treaty_number,
        res[i].days_left,
        res[i].days_left_before_the_next_payment,
        res[i].payment_status_KB,
        res[i].security_deposit_no_deposit,
        res[i].currency_conversion_only,
        res[i].currency,
        res[i].contact,
        res[i].additional_information,
        res[i].prolongation,
        res[i].improving_conditions,
        res[i].redundancy,
        res[i].akt_on_KB,
        res[i].payment_status_akt_on_KB,
        insurant,
        beneficiary,
        res[i].insurance_type_id.name,
        res[i].insurer_id.name,
        res[i].executor_id,
        res[i].status,
        res[i].payment,
        res[i].time_of_action.date_start + ' - ' + res[i].time_of_action.date_end,
        res[i].finance,
        res[i].date,
        res[i].subagent,
        res[i].insurance_object,
      ));    
    }
    return contracts;
  }

  public getContracts(): Observable<ContractsView[]> {
    let contracts = this.http.get(this.url, this.options)
      .map(this.extractContractsView)
      .catch(this.handleError);
    return contracts;
  }

Thanks for any help.

1
  • this.name will effectively always return prior to any of these calls being completed due to their async nature. You'd need to really look at restructuring this to perhaps return Observable<T> with RxJS map() operator via pipe() (depending on your version of RxJS) without subscribe() so that a consuming component can utilize the respective results via their own subscribe() or async pipe. You may also consider avoiding the loop and instead passing down the base object to a child component via something like @Input so that each can individually make the necessary http call. Commented Sep 5, 2018 at 21:51

1 Answer 1

1

You will need to refactor your API get calls to return an observable and subscribe to them in the consuming function. You are making two API calls per row. You can use the ForkJoin operator to combine the results of the two calls and then complete the insert into the new array. I am abbreviating the code. This should get you going in the right direction.

    public getInsurantOrBeneficiary(content_type: number, object_id: number): Observable<any> {
        if (content_type == 25) { 
          // Return an observable, do not subscribe here
          return this.http.get(endpoint, options)
            .map((response: Response) => response.json());
        }
    }

And then subscribe and process here:

public extractContractsView = (response: Response) => {

    let res = response.json();
    let contracts: ContractsView[] = [];

    for (let i = 0; i < res.length; i++) {

// Use a forkJoin to combine the results of 2 or more observables
forkJoin(
    this.getInsurantOrBeneficiary(),
    this.getInsurantOrBeneficiary()
)
.subscribe((result1: any, result2: any) => {
    contracts.push(new ContractsView(result1, result2))
});
}

Note that the loop will complete before all of the async results have returned. As pointed out in the comments, this may not be the best approach. However, what you want to do is possible using this methodology.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.