处理嵌套的observable

时间:2016-12-19 23:14:35

标签: angular typescript rxjs observable angular2-services

我在Angular 2中开始一个项目,我第一次与Observables交易并对一个非常具体的案例有一些疑问。

我有一个API服务,如下所示:

@Injectable()
export class UserAPI {

  [...]

  login(email: string, password: string): Observable<Response> {
    let params = new URLSearchParams();
    params.set('email', email);
    params.set('password', password);

    return this.$http.request(
      new Request({
        method: RequestMethod.Post,
        url: this.baseUrl + '/login',
        search: params
      }))
      .map((response: Response) => response.json());
  }

  [...]
}

我在包含调用此API的方法的用户服务上管理用户会话及其配置文件数据(当其会话处于活动状态时):

@Injectable()
export class UserService {

  [...]

  constructor(private userAPI: UserAPI, private storage: StorageService) {
  }

  login(email: string, password: string) {
    return this.userAPI.login(email, password).subscribe(
      (res) => {
        this.storage.store(Constants.storage.session, res.token);
      },
      (err) => {
        this.storage.destroy(Constants.storage.session);
      }
    );
  }

  [...]
}

现在,我还有一个处理登录表单的组件,如果成功,会将用户重定向到应用程序的私有区域,但如果失败,将显示错误消息(401,或者任何其他错误,如果偶然发生):

@Component({
  moduleId: module.id,
  selector: "auth-login",
  templateUrl: "auth.login.html"
})
export class LoginComponent {

  constructor(private router: Router, private userService: UserService) {
  }

  [...]

  login(): void {
    this.form.loading = true;
    this.form.error = -100; // arbitrary number

    this.userService.login(this.form.email, this.form.password);
      /*
      .subscribe(
      (res) => {
        this.router.navigate(["/home", {}]);
      },
      (err) => {
        this.form.error = err.status;
      },
      () => {
        this.form.loading = false;
      }
    );
    */
  }

  [...]
}

请注意userService.login()函数调用上的注释代码。这些是我打算对电话的成功/错误做的指示,但是我不能让它发挥作用。我希望将事物分开:用户服务管理会话部分,组件处理重定向或向用户显示出错的地方。

我做错了什么?什么方式去这里?嵌套的可观察物?使用组件和用户服务之间的承诺?还有其他方法吗?我一直在这里搜索,但找不到与我相似的案例。

1 个答案:

答案 0 :(得分:2)

我认为你不能把这样的订阅链接起来;你实际上期望thing.subscribe(...).subscribe(...)能够工作。相反,您可以使用.map.catch进行服务中的操作,并让组件.subscribe

login(email: string, password: string) {
  return this.userAPI.login(email, password)
      .map(res => {
        this.storage.store(Constants.storage.session, res.token);
        return res;
      })
      .catch(err => {
        this.storage.destroy(Constants.storage.session);
        return Observable.throw(err);
      });
}