简体   繁体   English

Angular 在返回数据之前等待订阅完成

[英]Angular wait for subscribe to finish before return data

Hi have a very simple function that call an endpoint to retrieve my user, I use it in my header to show the connected user but don't want to call the endpoint every time the header is rendered.嗨,有一个非常简单的函数可以调用端点来检索我的用户,我在标题中使用它来显示连接的用户,但不想在每次呈现标题时都调用端点。

So I'm trying something like this:所以我正在尝试这样的事情:

public getUser(): User {
    if (!this.user) {
     
      this.http.get<User>(environment.apiRoot + '/me').subscribe(res => {
        this.setUser(res);
        return this.user.value;
      }, err => {

      });
    } else {
      return this.user.value;
    }
  }

With the setUser function:使用setUser函数:

public setUser(u: User): void {
    if (!this.user) {
      this.user = new BehaviorSubject(u);
    } else {
      this.user.next(u);
    }
  }

And the BehaviorSubject : private user: BehaviorSubject<User>;BehaviorSubject : private user: BehaviorSubject<User>;

In my header component I call it like this in the ngOnInit :在我的头组件中,我在ngOnInit这样称呼它:

this.user = this.appState.getUser();
console.log(this.user);

But the user in the console.log is always undefined, why it doesn't wait for the subscription in the getUser function ?但是console.log里面的user一直是undefined,为什么不等待getUser函数里面的订阅呢?

You have an asynchronous function that you're calling with mixed reactive and imperative programming.您有一个异步函数,您正在使用混合反应式和命令式编程调用该函数。 When it comes to asynchronous functions, you should stay with the reactive approach and not try to determine when a certain code has finished, but instead just wait for it to finish and then invoke the callback or the responsible handler subsequently.当涉及到异步函数时,你应该坚持使用反应式方法,不要试图确定某个代码何时完成,而只是等待它完成,然后随后调用回调或负责的处理程序。

In your code the getUser() function is an async function, since you have the inner http.get() call.在您的代码中, getUser()函数是一个async函数,因为您有内部http.get()调用。 The http.get() will return an Observable , which you subscribe to inside your function unnecessarily. http.get()将返回一个Observable ,您在函数中不必要地subscribe它。 What you should do instead is return the inner observable from the function, and subscribe where you actually need it.你应该做的是从函数返回内部observable ,并在你真正需要它的地方subscribe

We can rewrite your getUser function like below (note that there is no need for the imperative setUser -function)我们可以像下面这样重写你的getUser函数(注意,不需要命令setUser函数)

public getUser(): Observable<User> {
    return this.http.get<User>(environment.apiRoot + '/me');
}

and in your outer scope subscribe to it like并在您的外部范围内订阅它,例如

this.appState.getUser().subscribe(user => {
    console.log(user)
});

To take it further, this makes it easier to work with observables in your templates as well.更进一步,这也使在模板中使用 observable 变得更容易。

Suppose you assign the returned observable to a variable, user$ , you don't even have to subscribe to it!假设您将返回的 observable 分配给变量user$ ,您甚至不必订阅它!

Just get the user like只要让用户喜欢

this.user$ = this.appState.getUser();

to get your observable, and then in your template use the async pipe to let Angular subscribe and unsubscribe automatically.获取您的 observable,然后在您的模板中使用async管道让 Angular 自动订阅和取消订阅。

<span>Hello, my name is {{user$ | async}}!</span>

If you want your getUser function to wait for subscription to finish, you will have to return observable.如果您希望getUser函数等待订阅完成,则必须返回 observable。 And then use .subscribe() with this.appState.getUser() .然后将.subscribe()this.appState.getUser()

public getUser(): Observable<User> {
    if (!this.user) {
      return this.http.get<User>(environment.apiRoot + '/me').pipe(map(res => {
        this.setUser(res);
        return this.user.value;
      }, err => {

      }));
    } else {
      return of(this.user.value);
    }
  }

this.appState.getUser().subscribe(user => {
    console.log(user)
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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