我正在学习Angular,但我不理解HTTP get()
请求中引起undefined TypeError
的情况。
在Angular服务中,我有以下两种方法。首先成功调用searchForCountries()
,然后调用searchForCyties()
并失败。
我试图在console.log(response)
上设置一个断点,但从未到达。
// That first one perfectly works and return the expected Observable
searchForCountries(): Observable<CountryResult[]> {
const queryUrl = `${this.geoNamesCountriesUrl}`;
console.log('query url: ', queryUrl);
return this.http.get(queryUrl).pipe( map( response => {
return <any>response['geonames'].map( result => {
return new CountryResult ({
name: result.countryName,
code: result.fipsCode
});
});
}));
}
// That one causes the message given below
searchForCities(query: string, country: string): Observable<CityResult[]> {
const queryUrl = `${this.geoNamesCitiesUrl}&postalcode=${query}&country=${country}`;
console.log('query url: ', queryUrl); // << -- I verified that the queryUrl returns an expected answer
return this.http.get(queryUrl).pipe( map( response => {
console.log(response); // << --- Why never reach that line and get the error below ??
return <any>response['postalcodes'].map( result => {
console.log(result);
return new CityResult ({
name: result.placeName,
cp: result.postalcode
});
});
}));
}
调用searchForCities()
会导致以下错误:
ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at subscribeTo (subscribeTo.js:41)
at subscribeToResult (subscribeToResult.js:6)
at SwitchMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/switchMap.js.SwitchMapSubscriber._innerSub (switchMap.js:47)
at SwitchMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/switchMap.js.SwitchMapSubscriber._next (switchMap.js:40)
at SwitchMapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:54)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next (map.js:41)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:54)
at DebounceTimeSubscriber.push../node_modules/rxjs/_esm5/internal/operators/debounceTime.js.DebounceTimeSubscriber.debouncedNext (debounceTime.js:48)
at AsyncAction.dispatchNext (debounceTime.js:62)
at AsyncAction.push../node_modules/rxjs/_esm5/internal/scheduler/AsyncAction.js.AsyncAction._execute (AsyncAction.js:63)
defaultErrorLogger @ core.js:1633
push../node_modules/@angular/core/fesm5/core.js.ErrorHandler.handleError @ core.js:1679
next @ core.js:4255
schedulerFn @ core.js:3491
push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub @ Subscriber.js:195
push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next @ Subscriber.js:133
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next @ Subscriber.js:77
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @ Subscriber.js:54
push../node_modules/rxjs/_esm5/internal/Subject.js.Subject.next @ Subject.js:47
push../node_modules/@angular/core/fesm5/core.js.EventEmitter.emit @ core.js:3483
(anonymous) @ core.js:3782
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:388
push../node_modules/zone.js/dist/zone.js.Zone.run @ zone.js:138
push../node_modules/@angular/core/fesm5/core.js.NgZone.runOutsideAngular @ core.js:3719
onHandleError @ core.js:3782
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.handleError @ zone.js:392
push../node_modules/zone.js/dist/zone.js.Zone.runTask @ zone.js:191
push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:496
ZoneTask.invoke @ zone.js:485
timer @ zone.js:2054
setInterval (async)
scheduleTask @ zone.js:2075
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:407
onScheduleTask @ zone.js:297
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:401
push../node_modules/zone.js/dist/zone.js.Zone.scheduleTask @ zone.js:232
push../node_modules/zone.js/dist/zone.js.Zone.scheduleMacroTask @ zone.js:255
scheduleMacroTaskWithCurrentZone @ zone.js:1114
(anonymous) @ zone.js:2090
proto.(anonymous function) @ zone.js:1394
push../node_modules/rxjs/_esm5/internal/scheduler/AsyncAction.js.AsyncAction.requestAsyncId @ AsyncAction.js:35
push../node_modules/rxjs/_esm5/internal/scheduler/AsyncAction.js.AsyncAction.schedule @ AsyncAction.js:28
push../node_modules/rxjs/_esm5/internal/Scheduler.js.Scheduler.schedule @ Scheduler.js:13
push../node_modules/rxjs/_esm5/internal/scheduler/AsyncScheduler.js.AsyncScheduler.schedule @ AsyncScheduler.js:31
push../node_modules/rxjs/_esm5/internal/operators/debounceTime.js.DebounceTimeSubscriber._next @ debounceTime.js:36
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @ Subscriber.js:54
push../node_modules/rxjs/_esm5/internal/operators/filter.js.FilterSubscriber._next @ filter.js:38
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @ Subscriber.js:54
push../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next @ map.js:41
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @ Subscriber.js:54
handler @ fromEvent.js:21
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:421
onInvokeTask @ core.js:3751
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:420
push../node_modules/zone.js/dist/zone.js.Zone.runTask @ zone.js:188
push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:496
invokeTask @ zone.js:1540
globalZoneAwareCallback @ zone.js:1566
我还尝试在catchError
上添加一个map()
,但是显然我没有达到map()
:
searchForCities(query: string, country: string): Observable<CityResult[]> {
const queryUrl = `${this.geoNamesCitiesUrl}&postalcode=${query}&country=${country}`;
console.log('query url: ', queryUrl);
return this.http.get(queryUrl).pipe(
map( (response) => {
console.log(response);
return <any>response['postalcodes'].map( (result) => {
...
});
}),
catchError((error): any => {
throw Error(`HTTP Error: ${error}`);
})
);
}
编辑
searchForCities()
的调用方式类似于ngOnInit()
:
fromEvent(this.el.nativeElement, 'keyup')
.pipe(
map((e: any) => e.target.value),
filter((text: string) => text.length > 2),
debounceTime(250),
map((query: string) => {
console.log('query ' + query);
this.citysearch.searchForCities(query, this.countrycode);
}),
switchAll()
)
.subscribe(
(results: CityResult[]) => {
this.cities = results;
},
(err: any) => {
console.log(err);
},
() => {
}
);
有什么想法吗?