作为我们安全的一部分,我们需要对用户进行身份验证,然后在我们调用服务获取数据之前获取权限。如何在Angular 2中进行一系列调用?计划是使安全部分成为一个单独的类,以确保用户通过身份验证并缓存权限。
@Injectable()
export class BankInfoService {
private _bankInfoUrl = 'http://ourwebsite/api/GetAllClabeBankCodes';
private _authenticateUrl = 'http://ourwebsite/api/AuthenticateUser';
private _getRightsUrl = 'http://ourwebsite/api/GetRights';
constructor(private _http: Http) { }
getBankInfos(): Observable<BankInfo[]> {
this._http.get(this._authenticateUrl);
rights = this._http.get(this._getRightsUrl);
return this._http.post(this._bankInfoUrl)
.map((response: Response) => <BankInfo[]> response.json().BankCodes)
.do(data => console.log('All: ' + JSON.stringify(data)))
.catch(this.handleError);
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
答案 0 :(得分:1)
Http调用是冷可观察的:每次订阅时都会重新创建它们,你需要的是创建一个热的observable,它将继续发出最后一个值。您可以使用将重播最后n
个值的connect()
来执行此操作,然后使用refcount()
开始发送。您也可以使用export class AuthService {
rights: Observable < Rights > ;
constructor(private http: Http) {
this.rights = this.http.get('url')
.map(response => new Rights(resp.json())) //transform http response to Rights object
.publishReplay(1); //always replay the last value / transform to hot observable
this.rights.connect();// start emitting
}
,只要订阅者收听流,就会继续发出值:
switchMap()
关于hot and cold observables here的好文章。
这是最简单的部分,您可以使用export class BankInfoService {
constructor(private authService: AuthService) {}
getBankInfos() {
return this.authService.rights.flatMap(() => this._http.post(this._bankInfoUrl))
.map((response: Response) => < BankInfo[] > response.json().BankCodes)
.do(data => console.log('All: ' + JSON.stringify(data)))
.catch(this.handleError);
}
}
运算符:
将每个值映射到Observable,然后使用switch展平所有这些内部Observable。
{{1}}
答案 1 :(得分:1)
我会创建一个执行此AAA任务的AuthGuard。 Guard可以使用使用ReplaySubject缓存数据的服务。以下是路由,服务,防护和组件如何协同工作的示例。
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser';
import {Routes, RouterModule, Route} from '@angular/router';
import {Injectable} from '@angular/core';
import {Router, CanActivate, ActivatedRouteSnapshot,
RouterStateSnapshot} from '@angular/router';
import 'rxjs/add/operator/switchMap';
import {Http} from '@angular/http';
import {ReplaySubject} from 'rxjs/ReplaySubject';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
@Injectable()
export class AaaService {
private subject = new ReplaySubject();
constructor() {
// replace Observable.of to your http calls
Observable.of('user')
.switchMap(x => Observable.of(['delete', 'edit']))
.catch(x => Observable.of([]))
.subscribe(this.subject);
}
getRights() {
return this.subject.asObservable();
}
}
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private aaaService: AaaService) {
}
canActivate(route: ActivatedRouteSnapshot, state:
RouterStateSnapshot): Observable<boolean> {
return this.aaaService.getRights()
.map((rights: Array<string>) => {
if (rights.length === 0) {
this.router.navigate('/login');
}
return true;
});
}
}
@Component({
selector: 'my-cpm',
template: `
<div>
hi from component. Rights: {{rights | async | json}}
</div>
`,
})
export class MyComponent {
rights;
constructor(private aaaService: AaaService) {
this.rights = aaaService.getRights();
}
}
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<router-outlet></router-outlet>
<a routerLink="/mypath">go to auth path</a>
</div>
`,
})
export class App {
name: string;
constructor() {
this.name = `Angular! v${VERSION.full}`
}
}
const routes = [
{
path: 'mypath',
component: MyComponent,
canActivate: [AuthGuard]
}
];
@NgModule({
imports: [BrowserModule, RouterModule.forRoot(routes)],
providers: [AaaService, AuthGuard],
declarations: [App, MyComponent],
bootstrap: [App]
})
export class AppModule {
}