0

I'm calling a Service from an onSubmit(). The service then calls a REST API for data. However the ordering is not what I'd expect. I think I have 2 issues here:

  1. The log @@@ CUSTOMER BEFORE RETURN doesn't seem to contain the retrieved data despite initialising the variable at the start of the method. So at this log line, it's still undefined. However at @@@ UNPACKED DATA the data is visible.
  2. Even if customer was not undefined at the return of loadCustomer, it looks like the line @@@ CUSTOMER IN onSubmit is executed before data is retrieved and not after, which will be a problem since I need to use the data afterwards!
  onSubmit(customerData) {
    let customer = this.customerService.loadCustomer(customerData)
    console.log("@@@ CUSTOMER IN onSubmit", customer)

    // use customer Object to process orders...
  }
import { HttpClient } from '@angular/common/http';
import { HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable()
export class CustomerService {

    constructor(private http: HttpClient) { }

    loadCustomer(customerId: number) {
        console.log("@@@ Customer ID to get: ", customerId)
        var myStr: string;
        var myObj: any;
        var customer: Object

        const httpOptions = {
            headers: new HttpHeaders({
                'Content-Type': 'application/json'
            })
        };

        this.http.get<any[]>('https://REGION.amazonaws.com/dev/customer', httpOptions).subscribe(
            data => {

                myStr = JSON.stringify(data);
                myObj = JSON.parse(myStr);

                console.log("@@@ UNPACKED DATA", myObj['data']['Items'][customerId-1])
                if (typeof myObj['data']['Items'][customerId] != "undefined")
                    customer = myObj['data']['Items'][customerId-1]

            },
            error => console.log('Failed to get customer.')
        );

        console.log("@@@ CUSTOMER BEFORE RETURN: ", customer)

        return customer;

    }
OUTPUT IN CONSOLE:
customer.service.ts:21 @@@ Customer ID to get:  2
customer.service.ts:51 @@@ CUSTOMER BEFORE RETURN:  undefined
cart.component.ts:64 @@@ CUSTOMER IN onSubmit undefined
customer.service.ts:38 @@@ UNPACKED DATA {customer_id: 2, address: "32 Big avenue", row_id: "a97de132-89ac-4f6e-89cd-2005319d5fce", name: "Dave Lawinski", tel_number: "777888999"}

From what I've gathered this looks like something to do with Observable / some form of asynchronous operation, however I've not been able to make sense of where I'm going wrong here.

solarflare
  • 880
  • 2
  • 8
  • 23
  • 1
    Does this answer your question? [How do I return the response from an Observable/http/async call in angular?](https://stackoverflow.com/questions/43055706/how-do-i-return-the-response-from-an-observable-http-async-call-in-angular) – R. Richards Dec 22 '20 at 14:34
  • Thanks for this - sorry it doesn't quite fix it. So from that post I understand that the `subscribe` function is what's 'asynchronous'. So I tried returning `customer` from within the `subscribe()`, but it still calls the `@@@ CUSTOMER IN onSubmit ` line before getting data and not after, therefore the output is essentially the same :( – solarflare Dec 22 '20 at 14:52

1 Answers1

1

you are returning an object before the http call returns, you need to return an observable and then subscribe to it in the component:

onSubmit(customerData) {
  this.customerService.loadCustomer(customerData)
    .subscribe((res) => {
        console.log("@@@ CUSTOMER IN onSubmit", res)
        // use res Object to process orders...
    })
}

and in your loadCustomer function:

loadCustomer(customerId: number) {
  const httpOptions = {
      headers: new HttpHeaders({
          'Content-Type': 'application/json'
      })
  };

  return this.http.get<any[]>('https://REGION.amazonaws.com/dev/customer', httpOptions)
    .pipe(map((result) => {
        const myStr = JSON.stringify(data);
        const myObj = JSON.parse(myStr);
        let customer; 

        console.log("@@@ UNPACKED DATA", myObj['data']['Items'][customerId-1])
        if (typeof myObj['data']['Items'][customerId] != "undefined") {
            customer = myObj['data']['Items'][customerId-1];
        }
        
        return customer;
    }));
}
Moshezauros
  • 2,493
  • 1
  • 11
  • 15
  • Thank you. However I'm getting an `Property 'map' does not exist on type 'Observable'` error when trying to use that `map` function. I've imported `import { map } from "rxjs/operators";` but still hasn't resolved it. I'm running Angular 9.0.2 on this project – solarflare Dec 22 '20 at 15:25
  • 1
    @solarflare, sorry, my mistake, ive updated the question, you need to add a pipe operator before the map – Moshezauros Dec 22 '20 at 15:35
  • Ah ok thank you - so I'm actually still getting undefined for `customer` within the onSubmit. Mine is actually different - so I have `res` being logged out instead of `customer` since that was giving me an error, but then `res` still shows up as undefined This is probably because `customer` if logged directly after `customer = myObj['data']['Items'][customerId-1];` is also undefined! – solarflare Dec 22 '20 at 15:39
  • 1
    yes you are right, you should log res, and not customer, in `onSubmit`, when you log customer just before returning it in the map operator, is it undefined? – Moshezauros Dec 22 '20 at 15:50
  • It is yes, so even in that if-block it's still undefined which is very strange. The `@@@ UNPACKED DATA` returns the data fine. So maybe it has some issue with storing this data within the variable `customer`? – solarflare Dec 22 '20 at 15:55
  • 1
    how about in `loadCustomer`, if you add console.log(customer) before returning it, does it have a value there? – Moshezauros Dec 22 '20 at 15:58
  • Ah sorry my fault - somehow was passing an incorrect customerId which wasn't returning any results! Thank you very much it's working as expected now :) – solarflare Dec 22 '20 at 16:05