【问题标题】:Issue with synchronous operation somewhere down a chain RxJS observables subscriptionRxJS observables 订阅链中某处的同步操作问题
【发布时间】:2016-08-24 13:14:22
【问题描述】:

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

此同步操作将数据设置在本地存储(同步)上,需要进一步向下链执行 http 调用(异步/可观察)。

这里是序列的摘要:

  1. 异步操作返回一个 observable 调用
  2. 在本地存储上同步操作设置数据
  3. 使用本地存储日期的异步操作并返回一个 observable
  4. 最终订阅

在调用 3. 时,本地存储上似乎没有数据可用 - 应该是由 2.

设置的

以上只是问题的简化。

这是完整的代码(打字稿):

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

  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);
  }

来自会话服务:

  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);
  }

用户帐户解析:

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
    });
  }
  ...

有人可以帮忙吗?

【问题讨论】:

    标签: rxjs observable rxjs5


    【解决方案1】:

    如果我正确理解您的问题,您希望延迟重定向用户,直到两个 HTTP 请求都完成。目前您订阅了您的 Observable,导致重定向在它观察到第一个结果时立即发生,在本例中是 userAccountService.resetPassword() 的结果。

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

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

    但是,拥有一个您不关心其结果的 Observable 是一个迹象,表明您的应用可能需要在这些日子里进行重构。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-10
      • 2017-03-26
      • 2020-10-28
      • 2018-08-30
      • 2017-08-24
      • 1970-01-01
      • 2021-10-23
      相关资源
      最近更新 更多