Angular onInit上的可观察订阅仅运行一次

Angular onInit上的可观察订阅仅运行一次,angular,typescript,angular2-observables,ngoninit,Angular,Typescript,Angular2 Observables,Ngoninit,我有一个带有名称的表和一个输入标记,当值更改时,它会过滤表的内容。 数据来自服务,并在服务上发出http请求 我有三种情况: 1-如果我只在ngOninit()上订阅this.ds.getDrogas(),表中会显示所有内容,但过滤器不起作用。 2-如果我仅在filterName()上订阅this.ds.getDrogas(),则表开始为空,但当我更改输入y的值时,表开始正常工作。如果我删除输入的内容,表格会显示所有的数据,如果我再次写入内容,过滤器就会工作。 3-如果我在这两个网站上都订阅了,

我有一个带有名称的表和一个输入标记,当值更改时,它会过滤表的内容。 数据来自服务,并在服务上发出http请求

我有三种情况:

1-如果我只在
ngOninit()
上订阅
this.ds.getDrogas()
,表中会显示所有内容,但过滤器不起作用。 2-如果我仅在
filterName()
上订阅
this.ds.getDrogas()
,则表开始为空,但当我更改输入y的值时,表开始正常工作。如果我删除输入的内容,表格会显示所有的数据,如果我再次写入内容,过滤器就会工作。 3-如果我在这两个网站上都订阅了,它将按预期工作。表格开始显示所有内容,当输入值更改时,过滤器工作

我知道
ngOnInit()
中的代码只运行一次,但订阅不应该一直监听可观察到的更改

我提前感谢你的帮助

服务方:

getDrogas(): Observable <HttpResponses> {
    return this.http.get<HttpResponses>(this.apiUrl +'/drogas')
  }
Table-Component.html:

<input  type="text" [(ngModel)]='contador' (ngModelChange)='filterName()'>

this.ds.getDrogas()
-返回一个可观察的。Angular不会在没有订阅的情况下从服务器请求数据。您可以在ngOnInit()中订阅它-这就是您获取初始数据的原因

我建议在
ngModelChange
处理程序中使用主题为declauteTime运算符,以防止每次更改时调用API。它将如下所示:

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  filterValue$ = new BehaviorSubject('');
  filterValue = '';

  constructor(private api: ApiSerive) {}

  ngOnInit(): void {
    this.filterValue$.pipe(
      debounceTime(DEBOUNCE_TIME),
      switchMap(filterValue => this.api.getData().pipe(
        map(dataFromServer => filterData(dataFromServer, filterValue)),
      )),
      /* UNSUBSCRIBE HERE on compoennt destroy */
      tap(filteredData => {
        console.log(filteredData);
        /* LOGIC OF UPDATE TABLE */
      }),
    ).subscribe();
  }

  onFilterChanged(value: string): void {
    console.log(value);
    this.filterValue$.next(value);
  }
}

function filterData(dataFromServer: any, filterValue): any {
  // SOME LOGIC HERE
  return dataFromServer;
}
完整代码在这里

附笔。 别忘了取消订阅组件中的可观察对象


我希望有帮助

我明白,但我不想有两个相等的订阅。如果我在服务上创建一个主题并使其发出一个值,我可以在我的组件中订阅该主题。因此,每次调用this.ds.getDrogas时,它都会通过主题发出值。这是一个好的解决方案吗?您必须订阅发出HTTP请求的Observable。我已经更新了一个答案,以显示它的外观。这是一个正确的答案,但是,我们应该考虑到共享逻辑,而不是复制粘贴,这是很简单的
filterName(){this.loadData()}
ngOnInit(){this.loadData()}
它没有复制粘贴。我已经编辑了我的答案,使之更符合最新情况。如果对您有效,请将其标记为答案。谢谢
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  filterValue$ = new BehaviorSubject('');
  filterValue = '';

  constructor(private api: ApiSerive) {}

  ngOnInit(): void {
    this.filterValue$.pipe(
      debounceTime(DEBOUNCE_TIME),
      switchMap(filterValue => this.api.getData().pipe(
        map(dataFromServer => filterData(dataFromServer, filterValue)),
      )),
      /* UNSUBSCRIBE HERE on compoennt destroy */
      tap(filteredData => {
        console.log(filteredData);
        /* LOGIC OF UPDATE TABLE */
      }),
    ).subscribe();
  }

  onFilterChanged(value: string): void {
    console.log(value);
    this.filterValue$.next(value);
  }
}

function filterData(dataFromServer: any, filterValue): any {
  // SOME LOGIC HERE
  return dataFromServer;
}