在链RxJS observables订阅的某个地方进行同步操作的问题

时间:2016-08-24 13:14:22

标签: rxjs observable rxjs5

我有一个同步操作,它在RxJS observables订阅链的某个地方运行。

此同步操作设置本地存储(同步)上的数据,以便执行http调用(异步/可观察)。

以下是序列摘要:

  1. 异步操作返回一个名为
  2. 的可观察对象
  3. 在本地存储上同步操作设置数据
  4. 使用本地存储日期进行异步操作并返回可观察的
  5. 最终订阅
  6. 3。被调用时,似乎数据在本地存储上不可用 - 应该由 2设置。

    以上只是问题的简化。

    这是完整的代码(在typescript中):

    这是由表单(位于组件中)调用的:

      resetPassword() {
        this.submitted = true;
        if (this.passwordResetForm.valid) {
          this.route.params.map(params => params['userAccountToken'])
            .switchMap(userAccountToken => {
              return Observable.concat(
                this.userAccountService.resetPassword(Object.assign(this.passwordResetForm.value.passwordReset, {token: userAccountToken})),
                this.sessionService.signinByUserAccountToken(userAccountToken)
              );
            })
            //Will require the UserAccountResolve below which will itself fail because 'x-auth-token' is not yet available on local storage
            .subscribe(() => this.router.navigate(['/dashboard']));
        }
      }
    
    来自UserAccountService的

      resetPassword(passwordResetForm) {
        return this.http.put(this.urls.USER_ACCOUNT.RESET_PASSWORD, passwordResetForm);
      }
    
    来自SessionService的

      signinByUserAccountToken(userAccountToken: string) {
        return this.http.post(format(this.urls.AUTHENTICATION.SIGNIN_BY_USER_ACCOUNT_TOKEN, {userAccountToken}), null)
          .do(response => this.setPersonalInfo(response.headers.get('x-auth-token')));
      }
    
      private setPersonalInfo(sessionToken) {
        localStorage.setItem('authenticated', 'true');
        localStorage.setItem('sessionToken', sessionToken);
        this.authenticated$.next(true);
      }
    

    UserAccountResolve:

    import {Injectable} from '@angular/core';
    import {Resolve, ActivatedRouteSnapshot} from '@angular/router';
    import {UserAccount} from '../shared/models/useraccount.model';
    import {AuthenticatedHttpClient} from '../shared/services/authenticated-http-client.service';
    import {URLS} from '../urls/URLS';
    
    @Injectable()
    export class UserAccountResolve implements Resolve<UserAccount> {
    
      private urls;
    
      constructor(private authenticatedHttpClient: AuthenticatedHttpClient) {
        this.urls = URLS;
      }
    
      resolve(route: ActivatedRouteSnapshot) {
        //Will fail
        return this.authenticatedHttpClient.get(this.urls.USER_ACCOUNT.USER_ACCOUNT)
          .map(response => response.json());
      }
    
    }
    

    AuthenticatedHttpClient:

    @Injectable()
    export class AuthenticatedHttpClient {
    
      static createAuthorizationHeader(headers: Headers) {
        //Is not available on local storage when required
        headers.append('x-auth-token', localStorage.getItem('sessionToken'));
      }
    
      constructor(private http: Http) {
      }
    
    
      get(url) {
        let headers = new Headers();
        AuthenticatedHttpClient.createAuthorizationHeader(headers);
        return this.http.get(url, {
          headers: headers
        });
      }
      ...
    

    有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

如果我正确理解您的问题,您希望延迟重定向用户,直到两个HTTP请求都完成。目前您订阅了Observable,导致重定向一旦观察到第一个结果就会发生,在这种情况下是userAccountService.resetPassword()的结果。

如果您只是想等待所有请求完成,您可以像这样订阅onCompleted:

observable.subscribe(
    _ => {},
    err => { /* Don't forget to handle errors */ },
    () => this.router.navigate(['/dashboard']))

然而,如果有一个Observable,你不关心它的结果是一个标志,那么你的应用程序可能需要一天的重构。