简体   繁体   中英

Return observable and set value in the same method with angular

I want a service that would return the observable and set a value to field in the same method.

Now my userService.getUserDetails() method looks like this:

private requestUrl: string;
private bic: string;
private id: string;
private name: string;

getUserDetails(): Observable<User> {
this.bic = 'aaa';
this.id= '123';

this.requestUrl = `${configs.api}v1/bics/` + encodeURIComponent(this.bic) + `/ids/` + encodeURIComponent(this.id) + `/users`;

const userObservable = this.http.get<User>(this.requestUrl).pipe(catchError(this.handleError));

userObservable.subscribe(data => this.name = data.name);

return userObservable;
}

I want to do two things when getUserDetails is called: 1) return Observable<User> 2) set the name value so I could access it later in other classes by injecting this service in constructors, without calling the http request again. I think I want to have something like this:

  getName() {
return this.name;
 }

So I'm not sure about the subscribe, because I'm getting undefined after try to use the value. What is the best approach here?

Try to use the observable like this:

   public name: string;
   public bic: string;
   public id: string;
   public getUserDetails(): Observable<User> {
        this.bic = '...';
        this.id = '...';
        this.requestUrl = `${configs.api}v1/bics/` + encodeURIComponent(this.bic) + `/ids/` + encodeURIComponent(this.id) + `/users`;

        return this.http.get<User>(this.requestUrl).pipe(catchError(this.handleError));
    }

Ideally, this method is in a service and does nothing else but to return the observable and do error-handling if needed.

In your component you could have this:

    constructor(private readonly _yourService: YourService) {}

    public ngOnInit(): void {
    this.getUserDetails();
    console.log(this._yourService.name) // can be undefined, since the observable is asynchronous and probably isnt finished yet
    }

    public getUserDetails(): void{
    this._yourService.getUserDetails().subscribe(
    data => {
    this._yourService.name = data.name;
    // start doing other things, this.name should be defined, if your service returned the data correctly.
    }
    )
    }

Alternatievly, you can also do all of this in your service, it's really your choice of design.

use "tap", in your service

name:any;
const userObservable = this.http.get<User>(this.requestUrl).pipe(
tap((res)=>{
    this.name=res;
}),
catchError(this.handleError)
);

Sometimes it's used a kind of "cache"

name:any;
const userObservable = (this.name)?of(name):
  this.http.get<User>(this.requestUrl).pipe(
    tap((res)=>{
      this.name=res;
    }),
      catchError(this.handleError)
    );

So, you always can subscribe to the function, the first time, make the call to http, the second use the value of name - of(name) return an observable

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM