Подтвердить что ты не робот

Angular2 - перемещение после завершения наблюдения

У меня есть http наблюдаемый, например, в моем 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;
        });
}

Я создал наблюдаемый и создал подписку (response), которая является возвращаемым значением успеха.

Теперь, в моем компоненте, я хочу вызвать UserService.logout() и THEN перейти к новому маршруту:

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

Очевидно, что это может произойти асинхронно, и я могу закончить навигацию до выхода из системы.

Используя promises, я мог бы сделать что-то вроде этого:

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

Как я могу сделать то же самое с наблюдаемыми? В моем классе UserService я хочу создать наблюдаемый, подписаться на него, сделать некоторые вещи с успехом или ошибкой, ТОГДА перейти от моего компонента представления.

4b9b3361

Ответ 1

Фактически вы можете сделать метод logout вернуть обещание и использовать его как обычно. Он не должен быть наблюдаемым:

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']))
}

Ответ 2

Наблюдаемый объект имеет метод, наконец, попробуйте. Не забывайте сначала импортировать:

import 'rxjs/operators/finally';

Ваш выход() будет выглядеть следующим образом:

 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 ----

    });
  }

Если вы действительно хотели использовать обещание:

import 'rxjs/add/operator/toPromise';

logout() {
  return this.http.delete(this.baseUrl + url, { headers: this.headers() })
    .map(res => res.json());

в компоненте .ts

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

Ответ 3

Вы не можете дождаться завершения Observable, потому что его поток может продолжаться бесконечно. Но вы можете вызвать router.navigate внутри метода subscribe:

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

Выход из системы должен вернуть Observable, а не подписку. Например:

    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 the Async pipe job.)