Angular2:如何正确订阅服务和组件内部的 Http.post observable?
Angular2: How to subscribe to Http.post observable inside a service and a component properly?
对于 JWT 身份验证,我发出 post 请求以使用现在与 Observables 一起使用的新 Http
模块获取令牌。
我有一个简单的 Login
组件显示表单:
@Component({
selector: 'my-login',
template: `<form (submit)="submitForm($event)">
<input [(ngModel)]="cred.username" type="text" required autofocus>
<input [(ngModel)]="cred.password" type="password" required>
<button type="submit">Connexion</button>
</form>`
})
export class LoginComponent {
private cred: CredentialsModel = new CredentialsModel();
constructor(public auth: Auth) {}
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred);
}
}
我有一个 Auth
服务发出请求:
@Injectable()
export class Auth {
constructor(public http: Http) {}
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers})
.map(res => res.json())
.subscribe(
data => this._saveJwt(data.id_token),
err => console.log(err)
);
}
}
效果很好,但现在我想在我的组件中显示错误消息,所以我需要在 2 个地方订阅(Auth
用于管理成功,Login
用于管理错误)。
我使用 share
运算符实现了它:
public authentificate(credentials: CredentialsModel) : Observable<Response> {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
const auth$ = this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers})
.map(res => res.json()).share();
auth$.subscribe(data => this._saveJwt(data.id_token), () => {});
return auth$;
}
在组件内部:
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred).subscribe(() => {}, (err) => {
console.log('ERROR component', err);
});
}
它有效,但我觉得做错了..
我只是转置了我们用 angular1 和 promises
做的方式,你有没有更好的实现方式?
您只能订阅服务中的事件和return对应的observable:
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
var obs = this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers})
.map(res => res.json())
.subscribe(
data => this._saveJwt(data.id_token)
);
return obs;
}
如果发生错误,您可以使用 catch
运算符捕获它:
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred).catch((err) => {
console.log('ERROR component', err);
});
}
编辑
如果你想订阅一个 observable 两次,你需要通过调用 share
方法来实现 "hot"。
您还可以利用 do
运算符并仅在组件中订阅:
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers})
.map(res => res.json())
.do(
data => this._saveJwt(data.id_token)
);
}
既然可以使用这种方法,为什么还要在 sharedService
中订阅!
@Injectable()
export class Auth {
constructor(public http: Http) {}
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers}) //added return
.map(res => res.json());
//.subscribe(
// data => this._saveJwt(data.id_token),
// err => console.log(err)
//);
}
}
@Component({
selector: 'my-login',
template: `<form (submit)="submitForm($event)">
<input [(ngModel)]="cred.username" type="text" required autofocus>
<input [(ngModel)]="cred.password" type="password" required>
<button type="submit">Connexion</button>
</form>`
})
export class LoginComponent {
private cred: CredentialsModel = new CredentialsModel();
constructor(public auth: Auth) {}
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred).subscribe(
(data) => {this.auth._saveJwt(data.id_token)}, //changed
(err)=>console.log(err),
()=>console.log("Done")
);
}
}
编辑
不过如果你想订阅 sharedService
和 component
你当然可以用这个方法。 但我不推荐这个,而是在编辑部分对我来说很完美之前。
我无法用你的代码测试它。但是看看我的 example here(tested)。单击 myFriends tab
,检查浏览器控制台和 UI。浏览器控制台显示 sharedService
的订阅结果 & UI 显示 component
.
的订阅结果
@Injectable()
export class Auth {
constructor(public http: Http) {}
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
var sub = this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers}) //added return
.map(res => res.json());
sub.subscribe(
data => this._saveJwt(data.id_token),
err => console.log(err)
);
return sub;
}
}
export class LoginComponent {
private cred: CredentialsModel = new CredentialsModel();
constructor(public auth: Auth) {}
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred).subscribe(
(data) => {this.auth._saveJwt(data.id_token)}, //not necessary to call _saveJwt from here now.
(err)=>console.log(err),
()=>console.log("Done")
);
}
}
对于 JWT 身份验证,我发出 post 请求以使用现在与 Observables 一起使用的新 Http
模块获取令牌。
我有一个简单的 Login
组件显示表单:
@Component({
selector: 'my-login',
template: `<form (submit)="submitForm($event)">
<input [(ngModel)]="cred.username" type="text" required autofocus>
<input [(ngModel)]="cred.password" type="password" required>
<button type="submit">Connexion</button>
</form>`
})
export class LoginComponent {
private cred: CredentialsModel = new CredentialsModel();
constructor(public auth: Auth) {}
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred);
}
}
我有一个 Auth
服务发出请求:
@Injectable()
export class Auth {
constructor(public http: Http) {}
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers})
.map(res => res.json())
.subscribe(
data => this._saveJwt(data.id_token),
err => console.log(err)
);
}
}
效果很好,但现在我想在我的组件中显示错误消息,所以我需要在 2 个地方订阅(Auth
用于管理成功,Login
用于管理错误)。
我使用 share
运算符实现了它:
public authentificate(credentials: CredentialsModel) : Observable<Response> {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
const auth$ = this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers})
.map(res => res.json()).share();
auth$.subscribe(data => this._saveJwt(data.id_token), () => {});
return auth$;
}
在组件内部:
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred).subscribe(() => {}, (err) => {
console.log('ERROR component', err);
});
}
它有效,但我觉得做错了..
我只是转置了我们用 angular1 和 promises
做的方式,你有没有更好的实现方式?
您只能订阅服务中的事件和return对应的observable:
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
var obs = this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers})
.map(res => res.json())
.subscribe(
data => this._saveJwt(data.id_token)
);
return obs;
}
如果发生错误,您可以使用 catch
运算符捕获它:
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred).catch((err) => {
console.log('ERROR component', err);
});
}
编辑
如果你想订阅一个 observable 两次,你需要通过调用 share
方法来实现 "hot"。
您还可以利用 do
运算符并仅在组件中订阅:
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers})
.map(res => res.json())
.do(
data => this._saveJwt(data.id_token)
);
}
既然可以使用这种方法,为什么还要在 sharedService
中订阅!
@Injectable()
export class Auth {
constructor(public http: Http) {}
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers}) //added return
.map(res => res.json());
//.subscribe(
// data => this._saveJwt(data.id_token),
// err => console.log(err)
//);
}
}
@Component({
selector: 'my-login',
template: `<form (submit)="submitForm($event)">
<input [(ngModel)]="cred.username" type="text" required autofocus>
<input [(ngModel)]="cred.password" type="password" required>
<button type="submit">Connexion</button>
</form>`
})
export class LoginComponent {
private cred: CredentialsModel = new CredentialsModel();
constructor(public auth: Auth) {}
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred).subscribe(
(data) => {this.auth._saveJwt(data.id_token)}, //changed
(err)=>console.log(err),
()=>console.log("Done")
);
}
}
编辑
不过如果你想订阅
sharedService
和 component
你当然可以用这个方法。 但我不推荐这个,而是在编辑部分对我来说很完美之前。
我无法用你的代码测试它。但是看看我的 example here(tested)。单击 myFriends tab
,检查浏览器控制台和 UI。浏览器控制台显示 sharedService
的订阅结果 & UI 显示 component
.
@Injectable()
export class Auth {
constructor(public http: Http) {}
public authentificate(credentials: CredentialsModel) {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
var sub = this.http.post(config.LOGIN_URL, JSON.stringify(credentials), {headers}) //added return
.map(res => res.json());
sub.subscribe(
data => this._saveJwt(data.id_token),
err => console.log(err)
);
return sub;
}
}
export class LoginComponent {
private cred: CredentialsModel = new CredentialsModel();
constructor(public auth: Auth) {}
submitForm(e: MouseEvent) {
e.preventDefault();
this.auth.authentificate(this.cred).subscribe(
(data) => {this.auth._saveJwt(data.id_token)}, //not necessary to call _saveJwt from here now.
(err)=>console.log(err),
()=>console.log("Done")
);
}
}