在 Angular 个组件之间通过服务共享 map/object/array 中的数据的最佳做法是什么

What is the best practice to share data in map/object/array by service among Angular components

我正在学习angular。当谈到使用服务进行数据共享时,许多人建议我们应该使用Subject like BehaviorSubject。 但是我们应该一直这样做吗?

@Injectable({
  providedIn: 'root'
})
export class DataService {

  private imageUrls = new Map<number, string>();
  public imageUrlsSubject = new BehaviorSubject(this.imageUrls);

   public size(): number {
     return this.imageUrls.size;
   }

   public set(id: number, url: string): void {
     this.imageUrls.set(id, url);
     this.imageUrlsSubject.next(this.imageUrls);
   }

   public get(id: number): string {
     return this.imageUrls.get(id);
    }


    public has(id: number): boolean {
      return this.imageUrls.has(id);
    }
}

我按照这种做法写了一个这样的服务。这让我想知道:我们真的需要 Subject 吗?在另一个组件只需要使用 DOM 中的地图的情况下,我可以 摆脱 imageUrlsSubject 吗?

<img   
  *ngIf="dataService.has(row.id)" 
  [src]="dataService.get(row.id).url">

在另一个组件中,我可能只需要调用 dogDataService.set 来更新地图。

this.dataService.set(id, url);

如果去掉 Subject,会不会带来一些潜在的弊端?

谢谢!

你只是在内部使用你的 BehaviorSubject,但你的 getter 并不依赖它。您当前的服务与其消费者完全同步,"yes",您现在编程的方式 imageUrlsSubject 并不是真正必要的。

使用 Subject 的真正优势在于您可以将其作为 Observable 提供给其他地方!人们不再只能访问 imageUrls 的当前值,而是可以访问 imageUrls 的当前值和所有未来值!他们被赋予了流而不是快照。

然后您有 3 个设计选项:

  • 总是return一个Observable。如果人们想要快照,他们必须通过管道传输 take(1)
  • 始终 return 一个 Observable,但添加一个 shorthand 函数 snap,return 是当前值。
  • 总是 return 一个快照(就像它当前在您的代码中所做的那样)并添加一个 watch 函数,该函数 return 是一个 Observable。

我会更进一步说你不应该保留一个单独的 imageUrls 属性 而应该依赖 imageUrlsSubject.value (仅用于 BehaviorSubjects)。我只是推荐这个,这样你 A) 不太可能忘记 subject.next(newValue) 当你改变你的价值 B) 再次提醒你你应该使用你的主题;p

这里是保持 get 默认同步行为并添加异步 watch.

的改编示例
@Injectable({
  providedIn: 'root'
})
export class DataService {
  public imageUrlsSubject = new BehaviorSubject(new Map<number, string>());

   public size(): number {
     return this.imageUrlsSubject.value.size;
   }

   public set(id: number, url: string): void {
     this.imageUrlsSubject.value.set(id,url);
     this.imageUrlsSubject.next(this.imageUrlsSubject.value);
   }

   public get(id: number): string {
     return this.imageUrlsSubject.value.get(id);
    }


    public has(id: number): boolean {
      return this.imageUrlsSubject.value.has(id);
    }

    public watch(): Observable<Map<number, string>> {
      return this.imageUrlsSubject.asObservable();
    }
}

现在,您可以在代码的其他地方订阅地图中的任何更改,您可以通过管道传递它,传递 pipe/observable,...