0

Prior to getting the current customer orders I need to return his name, so my related Service class part looks like the following:

Updated:

export class AuthService { customerNameUrl = 'customers/name/' + name; . . . getCustomerOrders(customerName: string): Observable<CustomerOrder[]> { let currentCustomerName = this.getCurrentCustomer(customerName).subscribe(customer => customer.name); console.log(currentCustomerName); <--- Error let customerOrders = this.http.get<CustomerOrder[]>(this.customerOrdersUrl); console.log(customerOrders); return customerOrders } getCurrentCustomer(name: string): Observable<Customer> { const url = this.customerNameUrl; return this.http.get<Customer>(url).pipe( tap(_ => this.log(`fetched customer name=${name}`, 'success')), catchError(this.handleError<Customer>(`getCustomer name=${name}`)) ); } . . . } 

But the first console.log shows subscribers instead of the required value. I have tried to add map operator to get only the name from the entity but didn't succeed, maybe added it in the wrong way, any idea?

1 Answer 1

5

The method subscribe returns a Subscriber. That makes sense right? The whole Observable and JS by nature, is mainly async. You fetch data async and you should somehow wait for it, and use a callback to continue with the returned data. See here for the main thread about this.

In your case that would mean that you will have to use something to make the Observables chain. Good thing there are a bunch of operators, there must be one we can use. In this case, the best operator would be mergeMap or concatMap. However, it's unclear to me why you would need the name of the customer, as you are not passing that to the get customer API. Nevertheless, does this solve your query?

getCustomerOrders(customerName: string): Observable<CustomerOrder[]> { return this.getCurrentCustomer(customerName).pipe( // here you have your customer object, but what do you want to do with it? mergeMap((customer) => this.http.get<CustomerOrder[]>(this.customerOrdersUrl)) ); } getCurrentCustomer(name: string): Observable<Customer> { const url = this.customerNameUrl; return this.http.get<Customer>(url).pipe( tap(_ => this.log(`fetched customer name=${name}`, 'success')), catchError(this.handleError<Customer>(`getCustomer name=${name}`)) ); } 
Sign up to request clarification or add additional context in comments.

6 Comments

customer object includes the customer name that I need to show in a mat-select control, my component template includes two selects, one is for customer names and the other shows each customer orders.
with mergeMap a console.log returns: Observable {_isScalar: false, source: Observable, operator: MergeMapOperator}
@Sami-L Yes, that's an Observable. You can use the async pipe inside your template to display it. Considering your comments and question, I strongly advise you to read the answer to a question I linked in my answer
thanks for the interesting answer link stackoverflow.com/a/44154594/1299388 , please kindly consider that I am not using the resulting customer name directly in the template, first I want to use it to make a second request in the same method, which will return the related orders, as the names of the methods are meaningful. giving the customer name to the template is the responsibility of getCurrentCustomer method.
@Sami-L I understand, just remember, whenever you have a network request, the method doing that request can -never- return the response of the request. This will always be wrapped in a Promise, returned through a callback function or in the form of an Observable. If you want to chain two requests, you use the mergeMap operator. This way -inside- the mergeMap, you will have access to the response of the first request, and can pass this along to the second request
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.