サービス呼び出しからmap
を実行しようとしていますが、エラーが発生しています。 サブスクライブは角度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
演算子が2つのコールバックを受け取りますが、コールバックを受け取るのは1つだけである必要があります。エラー処理コードを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
を返すことにより、実際にエラーをキャプチャしないことに注意してください-コンソールに表示されます。
私の場合、エラーはe2eテスト中にのみ発生しました。 AuthenticationInterceptorのthrowError
が原因でした。
WebStormのインポート機能を使用したため、間違ったソースからインポートしました。 RxJS 6.2を使用しています。
違う:
import { throwError } from 'rjxs/internal/observable/throwError';
正しい:
import { throwError } from 'rjxs';
ここでインターセプターの完全なコード:
import { Injectable } from '@angular/core';
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
@Injectable()
export class AuthenticationInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const reqWithCredentials = req.clone({withCredentials: true});
return next.handle(reqWithCredentials)
.pipe(
catchError(error => {
if (error.status === 401 || error.status === 403) {
// handle error
}
return throwError(error);
})
);
}
}
コードがブール値を返すだけのObservableを返しています。以下のように使用する必要があります
.map(response => <boolean>response.json())
あなたのケースで別の共通サービスcheckservice
を使用している場合は、単に使用することができます
this.service.getData().subscribe(data=>console.log(data));
これにより、戻り値の型がvoidのcheckLogin()
関数が作成されます
checkLogin():void{
this.service.getData()
.map(response => {
this.data = response;
this.checkservice=true;
}).subscribe(data=>{ });
this.checkService
を使用して状態を確認できます
関数がブール値を返すことを期待している場合は、次のようにします。
import { of, Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
checkLogin(): Observable<boolean> {
return this.service.getData()
.pipe(
map(response => {
this.data = response;
this.checkservice = true;
return true;
}),
catchError(error => {
this.router.navigate(['newpage']);
console.log(error);
return of(false);
})
)}
pipe(switchMap(
で他のオブザーバブルを返すのを忘れていました
this.dataService.getPerson(personId).pipe(
switchMap(person => {
//this.dataService.getCompany(person.companyId); // return missing
return this.dataService.getCompany(person.companyId);
})
)
JSON Web Tokenを使用してユーザーを認証しようとすると、この問題に直面していました。私の場合、認証インターセプターに関連しています。
ユーザーを認証するリクエストを送信する場合、トークンはまだ存在しないため、トークンを提供する必要はありません。
インターセプターにこれが含まれていることを確認します。
if (req.headers.get('No-Auth') == "True")
return next.handle(req.clone());
そして、次のようにヘッダー要求に{'No-Auth':'True'}
を提供します。
authenticateUser(user): Observable<any> {
const headers = new HttpHeaders({'No-Auth':'True'});
headers.append('Content-Type', 'application/json');
return this.httpClient.post(`${this.apiEndpoint}/auth/authenticate`, user, {headers: headers});
}
pipe(...)
の浮遊コンマ(,
)によってトリガーできますコンパイルは最後にこの余分なコンマをキャッチしません:
pipe(first(), map(result => ({ event: 'completed', result: result}),);
これは「見えない」undefined
演算子になり、パイプ全体を台無しにして、非常にわかりにくいエラーメッセージにつながります。この場合、実際のロジックとは関係ありません。
同じエラーを探してここに到着したので、これを書きました。これは将来誰かに役立つかもしれません。
Http.getおよび。subscribe()を介してリモートAPIを呼び出すコンストラクターからサービス変数を初期化しようとすると、同じエラーが発生します。
問題が何であるかを理解せずに多くのテストを行った後、私は最終的にそれを取得しました:私のアプリケーションには認証とHttpInterceptorがあり、http。 get(...)'No-Auth'ヘッダーなし。ここのようにそれらを追加し、問題を解決しました:
getData() {
var reqHeader = new HttpHeaders({ 'Content-Type': 'application/x-www-urlencoded','No-Auth':'True' });
return this.http.get(environment.urlApi.Literales, { headers: reqHeader });
}
なんて頭痛:(
私の場合、Angular-5では、メソッドにアクセスしてデータをサブスクライブしていたサービスファイルはインポートされませんでした。サービスファイルをインポートした後、正常に機能しました。
サービスをモックした後、ユニットテストを実行し、観測可能な例外をスローしている間も、まったく同じエラーメッセージが表示されます。
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をモックし、観測可能なデータを返します。その中には、必要なすべてのメソッドが含まれているため、そのデータは正常です。
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
型の値を渡すのではなく、返されるオブジェクトで期待される正確な関数を複製することで修正しました。
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