サービスコールから map
を実行しようとしていますが、エラーが発生します。
https://stackoverflow.com/questions/41995647/subscribe-is-not-defined-in-angular-2 を見てみると、サブスクライブするためには、演算子の中からリターンする必要があると書かれていました。returnステートメントもあります。
以下が私のコードです。
checkLogin(): Observable<boolean> {
return this.service.getData()
.map(
response => {
this.data = response;
this.checkservice = true;
return true;
},
error => {
// debugger;
this.router.navigate(['newpage']);
console.log(error);
return false;
}
)
.catch(e => {
return e;
});
}
エラーログです。
TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable
あなたのサンプルコードでは、map
演算子が1つのコールバックしか受け取らないはずなのに、2つのコールバックを受け取っています。エラー処理のコードをcatchコールバックに移すことができます。
checkLogin():Observable<boolean>{
return this.service.getData()
.map(response => {
this.data = response;
this.checkservice=true;
return true;
})
.catch(error => {
this.router.navigate(['newpage']);
console.log(error);
return Observable.throw(error);
})
}
また、catch
とthrow
の演算子をインポートする必要があります。
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
EDIT:
キャッチハンドラで Observable.throw
を返すことで、実際にはエラーを捕捉することはできませんが、コンソールにはエラーが表示されます。
あなたのコードはObservable
.map(response => <boolean>response.json())
もし、他の一般的なサービス checkservice
を使用している場合は、単に
this.service.getData().subscribe(data=>console.log(data));
これにより、checkLogin()
関数の戻り値を void にすることができます。
checkLogin():void{
this.service.getData()
.map(response => {
this.data = response;
this.checkservice=true;
}).subscribe(data=>{ });
そして、this.checkService
を使って条件をチェックすることができます。
ユニットテストを行っているときに、まったく同じエラーメッセージが表示され、サービスをモックした後に観察可能な例外が発生しました。
私はObservable.throw
に正確な関数とフォーマットを渡すことで解決しました。
サービスを呼び出し、データを取得するために subscribe
を行う実際のコードです。400
エラーを処理するための catch
に注目してください。
this.search(event).catch((e: Response) => {
if (e.status === 400) {
console.log(e.json().message);
} else if (e.url) {
console.log('HTTP Error: ' + e.status + ' ' + e.statusText,
'URL: ' + e.url, 'Info: ' + e.json().message));
}
}).finally(() => {
this.loading = false;
}).subscribe((bData) => {
this.data = bData;
});
サービス内部のコード
search() {
return this.someService.getData(request)
.do((r) => {
this.someService.defaultHeaders.delete('skipAlert');
return r;
})
.map((r) => {
return r.businessObjectDataElements.length && r.businessObjectDataElements || null;
});
}
SomeServiceをモックしてobservableデータを返してみましたが、必要なメソッドがすべて入っているので問題ありません。
someServiceApi = fixture.debugElement.injector.get(SomeService);
spyOn(someServiceApi, 'getData').and.returnValue(Observable.of({}));
上記のコードは問題ありませんが、Observable.throw({})
を渡してキャッチ/エラー条件をテストしようとしたとき、サービスからResponse
タイプのリターンを期待していたため、エラーが表示されました。
そのため、以下のサービスのモックリターンではエラーが発生していました。
someServiceApi.getData
.and.returnValue(Observable.throw(new Response({status: 400, body: [], message: 'not found error'})));
そこで私は、Response
型の値を渡すのではなく、期待される関数をそのままreturnオブジェクトで再現することで修正しました。
someServiceApi.getData
.and.returnValue(Observable.throw({status: 400, json: () => { return {message: 'not found error'}}, body: []}));
// see `json: () => { return {message: 'not found error'}}` inside return value