Angular 2的新HttpClient

时间:2017-09-08 06:53:06

标签: angular rxjs angular2-observables

我有一个简单而常见的场景,我无法用新的HttpClient来解决这个问题。我来自Angular 1和可链接的then()承诺,并且不确定如何使用Observable实现这一点。 (如果更新了英雄之旅教程以反映向HttpClient的转变,那将会很棒。)

我有一个主app.component.ts。此组件将调用AuthenticationService.login()中的authentication.service.ts

AuthenticationService有两个目的:

  1. 它协调有关身份验证的所有客户端/服务器通信。
  2. 它存储可以在任何和/或所有组件之间共享的身份验证信息。
  3. 代码非常简单(注意:这只是伪造的伪代码)

    app.component.ts:

    export class AppComponent {
      loggedIn: boolean = false;
    
      constructor(private authenticationService: AuthenticationService) {
      }
    
      login() {
        // I want to do this but don't know how
        this.authenticationService.login(this.userLoginForm.email, this.userLoginForm.password).then(function(loggedIn) {
          this.loggedIn = loggedIn;
        }
      }
    }
    

    authentication.service.ts:

    @Injectable()
    export class AuthenticationService {
      user: User;
    
      constructor(private http: HttpClient) {
        // do stuff
      }
    
      // Recommendations I'm reading tend to prefer using Observables
      // instead of Promises. But I like the `then()` chaining that
      // I'm not sure how to do with Observables
    
      // Return what here? Observable<boolean> ?
      login(email, password): Observable<boolean> {
          const url = `http://127.0.0.1/token/auth`;
    
          // post() returns a LoginResponse that we subscribe to and handle here,
          // but I want to return a promise-like object that will resolve to
          // a boolean
          return this.http.post<LoginResponse>(url, {email: email, password: password})
              .subscribe(
                loginResponse => {
                  if (loginResponse.error) {
                    // set user to a new unauthenticated user
                    this.user = new User();
                  } else {
                    this.user = JSON.parse(loginResponse.data.user) as User;
                  }
    
                  localStorage.setItem('currentUser', JSON.stringify(this.user));
    
                  // returning a boolean here to the caller would be nice
                  return this.user.id != null;
                }
              }
            );  
      );
    

    }

    我在这里缺少什么?这不是微不足道的吗?

    可以说,这里不需要返回布尔值。 app.component.ts只能读取AuthenticationService.user以了解用户是否已登录?那是这样做的吗?

    更一般地说,服务必须有一种方法来处理从服务器返回的数据,然后解决调用组件正在等待的承诺。如何做到这一点?

2 个答案:

答案 0 :(得分:1)

您可以使用Obervable.map将事物转换为您的服务应返回的内容(您希望在此处观察到一个boolean值)。在任何地方使用observable,然后将其更改为.subscribe in your component。

// Your service:

@Injectable()
export class AuthenticationService {

    user: User;

    constructor(private http: HttpClient) {
    // do stuff
    }

    login(email, password): Observable<boolean> {

        const url = `http://127.0.0.1/token/auth`;

        return this.http.post<LoginResponse>(url, { email: email, password: password })
            .map(loginResponse => {
                this.user = loginResponse.error ? new User() : (JSON.parse(loginResponse.data.user) as User);
                localStorage.setItem('currentUser', JSON.stringify(this.user));
                return this.user.id != null;
            }
    }        
}

// Your component
export class AppComponent {

    loggedIn: boolean = false;

    constructor(private authenticationService: AuthenticationService) { }

    login() {
        this.authenticationService.login(this.userLoginForm.email, this.userLoginForm.password).subscribe(loggedIn =>  this.loggedIn = loggedIn);
    }
}

答案 1 :(得分:0)

您可以使用toPromise()功能将sudo apt-get install libpq-dev python-dev 转换为Observable。现在,您的Promise将返回login,而不是Promise,您可以通过Observable链接它。

then