为什么我在`http.get()。pipe()`上得到“未定义”

时间:2018-07-25 08:56:33

标签: angular6 rxjs6

我正在学习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);
  },
  () => {

  }
);

有什么想法吗?

0 个答案:

没有答案