0

I have a service that starts by executing the getName function, and then when some data gets into the else block of the getPlace function, instead of a regular object, I get a subscriber (as you can see in the screenshot), although in theory I subscribe to changes where I assign values. it can be fixed? enter image description here

enter image description here

3 Answers3

1

As others have said, you can't treat an http request (the http.get) as procedural code. The http request is asynchronous and the code within the .pipe() method is only executed after the data is returned from the server.

So your getPlace() method, won't be able to simply return data by calling the _getPlace() method.

Instead of fighting against the way this works and trying to "fix" it. I would suggest that you handle both as Observables.

My code in a similar situation looks like this:

Service

import { Observable, of, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';

getProducts(): Observable<IProduct[]> {
    if (this.products) {
        return of(this.products);
    }
    return this.http.get<IProduct[]>(this.productsUrl)
        .pipe(
            tap(data => console.log('All Products', JSON.stringify(data))),
            tap(data => this.products = data),
            catchError(this.handleError)
        );
}

Component

    this.productService.getProducts().subscribe({
        next: (products: IProduct[]) => {
            this.products = products;
        },
        error: err => this.errorMessage = err
    });

Here, if the data has already been cached, it uses the RxJS of operator to convert the data back into an Observable.

That way you can subscribe to the result of getProducts and you'll get the cached data OR the retrieved data.

NOTE: Another option is to use RxJS declaratively and leverage the RxJS shareReplay(1) operator to automatically provide the caching for you. For more information on this technique, check this out: https://www.youtube.com/watch?v=Z76QlSpYcck&t=517s

DeborahK
  • 57,520
  • 12
  • 104
  • 129
0

You have to subscribe the function for getting the value

 public nameList :any;
    this.getPlace(placeId).subscribe(data => {
    //data hold your expected response
    this.nameList =data;
    
    });
Jobelle
  • 2,717
  • 1
  • 15
  • 26
  • Then I get the error This.getPlace (...). Subscribe is not a function. Actually, I have the same logic in the getplace function, but if I don't explicitly assign let data = this._getPlace (placeId) .subscribe ... but write let data; and then under it a subscription to getplace, then 3 undefined will arrive in data @Jobelle – Вячеслав Салоид Aug 14 '20 at 17:02
0

Observable are asynchronous and javascript use a single thread environment. If the javascript thread detects any async task, the task are handed to enclosing environment(Browser etc.) to execute it in a seperate thread. So your code runs like this.

  1. Main Thread call this._getPlace()
  2. Checks the statement this._getPlace() and hands off the execution to other thread.
  3. Main Thread return data variable (which is null) - this happens before Step2 is finished.

That's why the data returned is null.

To solve your problem, usemap instead of subscribe

 if(this._place.has(placeId)){
    return this._places.get(placeId)
  } else { 
    let data: any = this.getPlace(placeId).map( place => {
                                                    //do something here
                                                    //return something
                                                    }).first()
    return data;
  }
azer-p
  • 304
  • 1
  • 12