AngularアプリケーションでGuardを使用して、初期の重要なデータを解決しています。バージョン4のAngularでは、次のように処理していました。
_// app.routing.ts
routing = [{
path: '', component: AppComponent, canActivate: [ResolveGuard],
}];
// resolve.guard.ts
@Injectable()
export class ResolveGuard implements CanActivate {
constructor(
private _api: ApiService,
) { }
canActivate(): any {
return this._api.apiGet('my/url').map(response) => {
if ( response.status === 'success') {
// Consume data here
return true;
}
return false;
}).first();
}
}
_
Http on Angular 5 の新しいバージョンは.map()
プロパティを使用しなくなったため、これは機能しません。
.map()
を.subscribe()
に変更してもエラーはスローされませんが、アプリケーションは正しく解決されません。一方、.first()
および/または.map()
を使用すると、このバージョンで予想されるように、いくつかのエラーがスローされます。
この場合はどうすればよいですか?
初期データがロードされた場合にのみ、そのルートをアクティブ化する必要があります。
編集して、apiGet
関数に関する情報を追加します。
_constructor(private _http: HttpClient) {}
public apiGet(url: string): any {
return this._http
.get(this.apiUrl + url)
.catch(this.handleError.bind(this));
}
_
したがって、まず最初に、可能な場合、特にどのタイプがどこに属するかがわかっている場合は、any
の使用を避けてください。
export interface FooInterface {
status: string;
fooString : string;
fooNumber : number;
}
最初にサービスのインターフェースをクリーンな方法で定義し、次にガードクラスをリファクタリングします。
更新された回答 for rxjs
6.x
import { throwError, Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
@Injectable()
export class FooService {
constructor(private _http: HttpClient) {}
public apiGet(url: string): Observable<FooInterface> {
return this._http
.get<FooInterface>(this.apiUrl + url)
.pipe(
catchError(error => {
// do general error handling if necessary and throw
throwError(error);
})
);
}
}
ガードクラス:
import { of, Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
@Injectable()
export class ResolveGuard implements CanActivate {
constructor(
private fooService: FooService ,
) { }
canActivate(): Observable<boolean> {
return this.fooService.apiGet('my/url')
.pipe(
map(response => response.status === 'success'),
catchError(error => of(false))
);
}
元の回答 for rxjs
5.x
import { _throw } from 'rxjs/observable/throw':
constructor(private _http: HttpClient) {}
public apiGet(url: string): Observable<FooInterface> {
return this._http
.get<FooInterface>(this.apiUrl + url)
.catch(error => {
// do general error handling if necessary and throw
_throw(error);
});
}
ガードクラス:
import { of } from 'rxjs/observable/of';
@Injectable()
export class ResolveGuard implements CanActivate {
constructor(
private _api: ApiService,
) { }
canActivate(): Observable<boolean> {
return this._api.apiGet('my/url')
.map(response => {
let val = false;
if ( response.status === 'success') {
// Consume data here
val = true;
}
return val;
}).catch(error => {
// consume the error maybe?
of(false)
});
}
map
演算子をインポートするだけで、機能します:
import { Observable } "rxjs/Observable";
import "rxjs/add/operator/map";
canActivate(): Observable<boolean>{
return this._api.apiGet('my/url').map(response => {
if ( response.status === 'success') {
// Consume data here
return true;
}
return false;
});
}