【问题标题】:How to avoid writing same http subscribe blocks for different components?如何避免为不同的组件编写相同的 http 订阅块?
【发布时间】:2021-05-17 15:46:48
【问题描述】:

假设有一个服务将用于 http 请求调用。两个不同的组件(可能超过两个)将通过该服务使用相同的 observables 发送相同的请求。在获得应该分配给的结果后全局变量(组件没有父子或子父的关系)。下面我为所有组件编写了相同的代码块。有没有更好的方法来编写这个函数并通过返回相同的值来调用?

服务

  getStudents() {
    const requestUrl = this.apiUrl + 'students/';
    return this.httpClient.get(requestUrl);
  }

组件1

  studentList:Student[]=[];
  getStudents.subscribe((students:Student[])=>{
      this.studentList=students;
      //Some operations
  })

组件2

  studentList:Student[]=[];
  getStudents.subscribe((students:Student[])=>{
       //Some operations 
  this.studentList=students;
  })

【问题讨论】:

  • 您可以将您传递给.subscribe() 的匿名函数重构为一个命名函数,然后简单地传递函数的名称。

标签: javascript angular typescript rxjs


【解决方案1】:

我不喜欢全局状态,但如果你想使用全局状态在组件之间维护相同的学生列表,那么该状态也可以存在于服务中(而不是单独存在于每个组件中)

所以,例如:

服务


studentList:Student[] = [];

setStudents(students:Student[]) {
  this.studentList = students;
  // Operations involved with setting students
}

updateStudents() {
  const requestUrl = this.apiUrl + 'students/';
  return this.httpClient.get(requestUrl).pipe(
    tap(this.setStudents)
  );
}

组件

ngOnInit(){
  this.service.updateStudents().subscribe();
}

【讨论】:

  • 我也不是粉丝。但我需要他们迭代 ngFor
  • @TimuçinÇiçek Angular 的异步管道很好地解决了这个问题:)。如果组件不使用内部状态呈现,您可以关闭该组件的更改检测。在整个项目中,这最终可以提高性能。这不是必须的,但是嘿。
【解决方案2】:

你可以在你的服务中拥有一个 Observable,

studentsReceived:Subject = new Subject();

getStudent() 成功后,您可以发出下一个 studentReceived 值。

现在你可以在你的组件中订阅studentsReceived,API调用成功后你会收到每个订阅组件的通知。

studentRecived.subscribe(data=>{ // do some code })

您必须在 AppComponent 等更高级别的组件上调用此 getStudent()。

【讨论】:

  • 但是这样我将无法在组件访问时发送请求。我想在每个组件的 onInit 上发送请求
  • 然后你可以在你的服务中保留一个私有变量并在成功回调中更新它。创建一个 getter 以访问 getter 组件中的该变量,您可以检查变量是否具有值,如果没有,则可以再次调用 getStudent()
【解决方案3】:

这里有 2 件重要的事情:

1) If you dont want to repeat the same block of code, then create a method in the service file, 
and call it in the component. Something like this: 

SERVICE: 

makeSubcription(componentVariableName) {
  this.yourObservable.subcribe(subscribedValue => {
     componentVariableName = subscribedValue;
  })
}

In your Component, you can do this: 

yourComponentMethod() {
  this.service.makeSubscription(this.studentLists);
}


************

2) If you dont want to make a service call too many times, what you can do is, 
use Behavior Subject and try to store the values, so that you are subscribing to the observable and not the actual API call. Something like this: 


private initialValuesForObservable: YourObjectModel = {}; // or null;

private observableSource: BehaviorSubject<YourObjectModel> = 
  new BehaviorSubject<YourObjectModel>(this.initialValuesForObservable);

public subscribableObservable: Observable<YourObjectModel> = 
  this.observableSource.asObservable();


setObservableValue(data: YourObjectModel) {
  this.observableSource.next(data);
}

getObservableData() {
  return this.subscribableObservable;
}



In your COMPONENT; 

this.service.getObservableData().subscribe(latestObservableData => {
  this.schoolList = latestObservableData;
});

【讨论】:

    猜你喜欢
    • 2012-03-25
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多