【问题标题】:Load and Reload data in service在服务中加载和重新加载数据
【发布时间】:2019-12-05 15:14:39
【问题描述】:

我有一个角度服务如下:

export class AuthService {

  private data$: Observable<DataModel[]>;

  constructor(private noteService: NoteService, private dataService: DataService) { }

  getData() {

    this.data$ = this.dataService.get();

  }

  authorize(requirement: Requirement) : Observable<boolean> {

    // Code that uses $data. Example:

    return this.data$.pipe(
      map(data => data.type == 12))
    );

  }

}

DataService 就是以下内容:

export class DataService {

  constructor(private httpClient: HttpClient) { }

  public get(): Observable<DataModel[]>> {
    return this.httpClient.get<DataModel[]>>(`auth/data`);
  }  

}

我在调用授权方法的组件和指令中注入AuthService

方法authorize需要使用data$设置data$

当检测到通知时,还必须使用getData() 重新加载data$

this.noteService.get().subscribe((note: Note) => { 

  if (note.code == 0) 
    this.getData(); // Reload data

});

问题

我不确定如何将此要求集成到 AuthService 中。

  1. 如何判断data$是否被定义并获取初始数据?
  2. 在哪里检查是否收到代码为 0 的通知并重新加载data$
  3. 如何确保 authorize 方法中的代码等待 data$ 完成加载,以防在调用授权时加载?
    是因为最初被加载还是因为正在重新加载?

【问题讨论】:

  • 您能否分享您的DataService 的相关部分,以帮助我更好地了解您的 observable 的来源?
  • 我只是更新我的答案。 DataService 使用 HttpClient 从 API 获取数据

标签: angular typescript rxjs angular8


【解决方案1】:

如何检查data$是否被定义并获取初始数据?

if (!this.data$) {
 this.getData()
}

在哪里检查是否收到代码为 0 的通知并重新加载数据$?

您可以在noteService 中检查此条件,并使用主题让noteService 的任何消费者收到通知:

note.service.ts

private notificationReceivedSubject = new Subject();
public notificationReceived$ = this.notificationReceivedSubject.asObservable();

this.noteService.get().subscribe((note: Note) => { 

  if (note.code == 0) {
    this.notificationReceivedSubject.next(true);
  }

});

auth.service.ts

constructor (private noteService: NoteService, /* ... */) {
 this.noteService.notificationReceived$
  .subscribe(() => this.getData()); // Reload data when notification is received
}

如果在调用授权时正在加载,如何确保授权方法中的代码等待data$完成加载?

这可能需要您对当前做事的方式进行一些改变。 看起来另一个实体取决于来自authService 的状态(data$)。 在这种情况下,我会使用 BehaviorSubject 来跟踪最后发出的值。

之前有一些改动:

auth.service.ts

private dataStore = new BehaviorSubject(null);
public data$ = this.dataStore.asObservable();

get data () {
 return this.dataStore.value; // Get the current value
}

getData () {
 this.dataStore.next(null); // `data` currently not available

 this.dataService.get()
  .subscribe(data => this.dataStore.next(data));
}

这个问题的答案是这样的:

this.authService.authorize(r)
 .pipe(
  tap(v => !v ? this.showLoader() : this.hideLoader()),
  filter(v => !!v) // Get data only when it is ready
 ).subscribe(d => console.log('data ready!', d))

【讨论】:

    【解决方案2】:

    我会省略订阅。你可以这样做:

    export class AuthService {
    
      private data$: Observable<DataModel[]>;
      private note$: Observable<NoteModel[]>;
    
      constructor(private noteService: NoteService, private dataService: DataService) {
        this.note$ = this.noteService.get();
    
        this.data$ = this.note$.pipe(
          filter(note => note && note.code == 0),
          switchMap(note => this.dataService.get()),
        );
      }
    }
    

    【讨论】:

    • 我不确定我是否遗漏了什么,但您从哪里获取初始数据来填充data$?我的意思是,当authService 第一次注入时应该调用dataService.get()。然后每次noteService 发出代码为 0 的注释时再次调用它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多