【问题标题】:angular2 - Navigate after observable is completeangular2 - 在 observable 完成后导航
【发布时间】:2016-05-22 22:13:52
【问题描述】:

我有一个像这样的http observable,在我的UserService

logout() {
    return this.http.delete(this.baseUrl + url, {
          headers: this.headers()
        }).map((res: IResponse) => {
          var json = res.json();
          json.headers = res.headers;
          return json;
        }).subscribe((response) => {
          //DO SOMETHING, THEN ----
          return res;
        });
}

我创建了一个 observable,并创建了一个订阅 (response),这是返回的成功值。

现在,在我的组件中,我想调用 UserService.logout() 然后导航到新路线:

logout() {
    this.userService.logout();
    this.router.navigate(['LandingPage']);
  }

显然,这可能是异步发生的,我可能最终会在我注销之前导航。

使用承诺,我可以做这样的事情:

this.userService.logout().then(() => { this.router.navigate(['LandingPage']); });

我怎样才能对 observables 做同样的事情?在我的UserService 类中,我想创建一个可观察对象,订阅它,在成功或错误时做一些事情,然后从我的视图组件中导航。

【问题讨论】:

    标签: angular observable


    【解决方案1】:

    注销需要返回 Observable 而不是 Subscription。 例如:

        logout(): Observable<T> {
            return this.http.delete(this.baseUrl + url, {
                  headers: this.headers()
                }).map((res: IResponse) => {
                  var json = res.json();
                  json.headers = res.headers;
                  return json;
                })
                .catch((err)=>Observable.empty()) // return empty if error
                .share(); // to ensure that no duplicate http calls can occur
     
        }
    
        //in component:
    
        this.service.logout()
          .do(()=>this.router.navigate(['LandingPage']);)//do stuff
          .subscribe((res:any)=>{});
    
        //or with template async pipe:
    
        public result$ = Observable<T>;
    
        result$ = this.service.logout()
          .do(()=>//do stuff);
    
        //in template:
     
        {{(result$ | async)?.id}}
        or simply
        {{result$ | async}}
    
        // P.s. do not forget about unsubscribe(), thats why I prefer to use async (since that's the Async pipe's job.)

    有关运算符/方法的更多信息:https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md

    【讨论】:

      【解决方案2】:

      Observable 对象终于有了方法,试试吧。 不要忘记先导入:

      import 'rxjs/operators/finally';
      

      您的 logout() 将是:

       logout() {
        return this.http.delete(this.baseUrl + url, { headers: this.headers() })
          .map(res => res.json())
          .finally(() => this.router.navigate(['LandingPage']))
          .subscribe((response) => {
            //DO SOMETHING, THEN ----
      
          });
        }
      

      如果你真的想使用 Promise:

      import 'rxjs/add/operator/toPromise';
      
      logout() {
        return this.http.delete(this.baseUrl + url, { headers: this.headers() })
          .map(res => res.json());
      

      在component.ts中

      var aPromise = this.userService.logout().toPromise();
      aPromise.then(() => {
          this.router.navigate(['LandingPage']);
      });
      

      【讨论】:

      • 你拯救了我的一天!我花了 5 个小时终于解决了我的问题
      • 太棒了!只是回报社会。很高兴能为您提供帮助。
      • finally() 效果很好,但您必须正确导入:import 'rxjs/add/operator/finally';
      【解决方案3】:

      您不能等待Observable 完成,因为它的流可能会无限期地继续。但是你可以在subscribe 方法中调用router.navigate

      logout() {
        return this.http.delete(this.baseUrl + url, { headers: this.headers() })
          .map((res: IResponse) => res.json())
          .subscribe((response) => {
            //DO SOMETHING, THEN ----
            this.router.navigate(['LandingPage']);
          });
        }
      

      如果这还不够,subscribe 返回一个Subscription,其unsubscribe 方法停止等待Observable 的数据。因此,如果必须,您可以等待超时时间并致电unsubscribe

      【讨论】:

        【解决方案4】:

        您实际上可以让logout 方法返回一个promise 并正常使用它。它不必是可观察的:

        logout() {
            return new Promise((resolve, reject) => {
                this.http.delete(this.baseUrl + url, { headers: this.headers() })
                    .map((res: IResponse) => {
                      var json = res.json();
                      json.headers = res.headers;
                      return json;
                    })
                    .subscribe(data => {
                      //DO SOMETHING, THEN ----
                      resolve(data);
                    }, error => reject(error));
            });
        }
        
        logout() {
          this.userService.logout().then(response => this.router.navigate(['LandingPage']))
        }
        

        【讨论】:

        • 非常有用的例子。谢谢:-)
        猜你喜欢
        • 2018-08-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-06
        • 1970-01-01
        • 2018-12-18
        • 2016-09-15
        相关资源
        最近更新 更多