Angular 4 Observable呼叫服务多次

时间:2017-09-22 12:37:50

标签: angular

我想按国家搜索城市。

我有两个不同的共享组件: 第一个用于国家搜索,这将发出选定的国家ID 然后第二个共享组件获取此国家/地区ID并传递给服务 但它不会过滤城市并返回数据库中的所有城市 当我调试休息服务时: 如果我不通过countryId它是工作并返回所有城市, 但我通过countryId;不久之后countryId值改变(null或0) 并返回整个城市。 这个场景有什么问题。 感谢。

//Component
export class CitySharedComponent implements OnInit {

  cities = new Array<City>();
  searchTerm$ = new Subject<string>();
  public selectedCountryId = new BehaviorSubject(0);
  @Input() countryId: any;

  constructor(private service: CityService) { }

  ngOnInit() {
    this.service.search(this.searchTerm$, this.selectedCountryId.getValue(), 1)
      .subscribe(results => {
        this.cities = results;
      });
  }

  onKeyup(searchText: string) {
    if (searchText != null)
      this.searchTerm$.next(searchText);
  }


  ngOnChanges(changes: { [propName: string]: SimpleChange }) {
    if (changes['countryId']) {
      if (changes['countryId'].currentValue == null || changes['countryId'].currentValue == undefined) 
        changes['countryId'].currentValue = 0;
      this.cities = null;
      this.selectedCountryId.next(changes['countryId'].currentValue);
    }

  }
}

//Service
search(terms: Observable<string>, countryId, lang): Observable<City[]> {
    var headers = new Headers();
    headers.append('Authorization', `bearer ${this.auth_key}`);
    headers.append('Content-Type', 'application/json');
    return terms
      .distinctUntilChanged()
      .switchMap(term => this.http.get(`${this.url}/search/${countryId}/${lang}/${term}`, { headers })
        .map(data => data.json())
      )
  }

2 个答案:

答案 0 :(得分:1)

无法在代码中找到ngOnDestroy。你需要在destroy中取消订阅你的Observable。

答案 1 :(得分:0)

嗯,即时错误是您没有订阅国家/地区ID主题,这就是为什么当您从中发出新值时没有变化的原因 - 只是没有人在听。您刚刚在ngOnInit()中选择了第一个值并将其传递给search()。它永远不会改变。

除此之外,不要更改changes集合中的任何内容。更改不属于您的数据通常是个坏主意,因此将其视为只读集合。它可以更简单:this.selectedCountryId.next(changes['countryId'].currentValue || 0);

<强>更新

可以做得更简单。您根本不需要了解任何可观察的服务。让它只是获取原始值。处理可观察物是另一个问题。

//Component
export class CitySharedComponent implements OnInit {

  cities = new Array<City>();
  searchTerm$ = new Subject<string>();

  public selectedCountryId = new BehaviorSubject(0);

  // if you don't need to store this value for your component then
  // you can safely remove getter and this field.
  // just leave setter, it will be enough.
  private _countryId: any;

  @Input()
  get countryId: any {
    return this._countryId;
  }
  set countryId(value: any) {
    this._countryId = value;
    this.selectedCountryId.next(this._countryId || 0);
  }

  constructor(private service: CityService) { }

  ngOnInit() {
    this.searchTerm$.distinctUntilChanged().combileLatest(
        this.selectedCountryId.distinctUntilChanged(), (_term, _countryId) => {
            return {
                term: _term,
                countryId: _countryId
            }
        }
    )
    .switchMap(t => this.service.search(t.term, t.countryId, 1))
    .subscribe(results => {
      this.cities = results;
    }); // and of course do not forget to unsubscribe from this
  }

  onKeyup(searchText: string) {
    if (searchText != null)
      this.searchTerm$.next(searchText);
  }

}

//Service
search(term: string, countryId, lang): Observable<City[]> {
    var headers = new Headers();
    headers.append('Authorization', `bearer ${this.auth_key}`);
    headers.append('Content-Type', 'application/json');
    return this.http.get(`${this.url}/search/${countryId}/${lang}/${term}`, { headers })
        .map(data => data.json());
}