Angular 2 的新 HttpClient 中的 Observable Chaining
Observable Chaining in Angular 2's new HttpClient
我有一个简单而常见的场景,但我无法理解使用新 HttpClient
执行此操作的正确方法。我来自 Angular 1 和 chainable then()
承诺,但不确定如何使用 Observables 实现这一点。 (如果更新英雄之旅教程以反映向 HttpClient 的转变,那就太好了)。
我有一个主app.component.ts
。该组件将在 authentication.service.ts
.
中调用 AuthenticationService.login()
AuthenticationService
有两个目的:
- 它协调有关身份验证的所有 client/server 通信。
- 它存储可以在任何 and/or 所有组件之间共享的身份验证信息。
理想情况下代码非常简单(注意:这只是人为的伪代码)
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;
}
}
);
);
}
我在这里错过了什么?这不是微不足道的吗?
可以说,这里不需要 return 布尔值。 app.component.ts
只读AuthenticationService.user 就可以知道用户是否登录了?是这样吗?
更一般地说,服务肯定必须有一种方法来处理来自服务器的数据 return,然后解决调用组件正在等待的承诺。如何做到这一点?
您可以使用 toPromise() 函数将 Observable
转换为 Promise
。现在你的 login
将 return Promise
,而不是 Observable
,你可以通过 then
s.
链接它
login(email, password) : Promise {
const url = `http://127.0.0.1/token/auth`;
return this.http.post<LoginResponse>(url, {email: email, password: password})
.toPromise().then(loginResponse => {
this.user = loginResponse.error ? this.user = new User() :
JSON.parse(loginResponse.data.user) as User;
localStorage.setItem('currentUser', JSON.stringify(this.user));
return this.user.id !== null;
});
}
您可以使用 Obervable.map 将事物转换为您的服务应该 return 的东西(您需要一个可观察的布尔值)。在任何地方都使用 observable,因此在您的组件中将 .then 更改为 .subscribe。
// 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);
}
}
我有一个简单而常见的场景,但我无法理解使用新 HttpClient
执行此操作的正确方法。我来自 Angular 1 和 chainable then()
承诺,但不确定如何使用 Observables 实现这一点。 (如果更新英雄之旅教程以反映向 HttpClient 的转变,那就太好了)。
我有一个主app.component.ts
。该组件将在 authentication.service.ts
.
AuthenticationService.login()
AuthenticationService
有两个目的:
- 它协调有关身份验证的所有 client/server 通信。
- 它存储可以在任何 and/or 所有组件之间共享的身份验证信息。
理想情况下代码非常简单(注意:这只是人为的伪代码)
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;
}
}
);
);
}
我在这里错过了什么?这不是微不足道的吗?
可以说,这里不需要 return 布尔值。 app.component.ts
只读AuthenticationService.user 就可以知道用户是否登录了?是这样吗?
更一般地说,服务肯定必须有一种方法来处理来自服务器的数据 return,然后解决调用组件正在等待的承诺。如何做到这一点?
您可以使用 toPromise() 函数将 Observable
转换为 Promise
。现在你的 login
将 return Promise
,而不是 Observable
,你可以通过 then
s.
login(email, password) : Promise {
const url = `http://127.0.0.1/token/auth`;
return this.http.post<LoginResponse>(url, {email: email, password: password})
.toPromise().then(loginResponse => {
this.user = loginResponse.error ? this.user = new User() :
JSON.parse(loginResponse.data.user) as User;
localStorage.setItem('currentUser', JSON.stringify(this.user));
return this.user.id !== null;
});
}
您可以使用 Obervable.map 将事物转换为您的服务应该 return 的东西(您需要一个可观察的布尔值)。在任何地方都使用 observable,因此在您的组件中将 .then 更改为 .subscribe。
// 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);
}
}