【问题标题】:Angular, RxJs Service stores - Why BehaviouralSubject is better to store array data than array?Angular,RxJs 服务存储 - 为什么 BehaviouralSubject 存储数组数据比存储数组更好?
【发布时间】:2020-10-12 19:47:14
【问题描述】:

在许多 RxJs 服务存储教程(可能全部)中 - BehaviouralSubjects 用于在存储服务中存储数据。 例如这里: https://dev.to/avatsaev/simple-state-management-in-angular-with-only-services-and-rxjs-41p8

我想我会理解这个概念,如果在我的应用程序的某个地方我需要订阅我的数组数据。但是,就像在教程中一样,BehaviouralSubject 是私有的,我需要使用服务方法来获取它的价值,所以我不能只是订阅它。

使用 BehaviouralSubject 有什么真正的好处?使用数组更容易..

存储数组数据的最佳方式是什么,它来自api,每次调用api时都会扩展?

【问题讨论】:

    标签: angular service rxjs store


    【解决方案1】:

    我不是专家,但这就是我理解 Observable 的方式,以及它们相对于简单数组的优势。


    最终,我们希望一个值在模板发生变化时被动地更新自身,而无需手动检查。

    类似这样的:
    <div>{{ observableData$ | async }}</div>

    observableData$ 变量是一个 Observable(由结尾 $ 的约定表示),它发送异步消息,可以使用 async 管道在模板中展开。

    您的模板可以像使用简单数组一样轻松使用它。
    例如。 <div>{{ [1, 2, 3] }}</div>

    但 Observable 只是数据的
    想象一条河流,它有一个定向的stream/水分子流。但是流更多的是动词而不是名词。

    每条河流都需要一个。水分子实际上来自哪里?
    rxjs 中,Observable 的“源”称为Subject

    Observable 不会“做”任何事情,只是提供从“源”/Subject 到您所在位置subscribing 到数据的管道。就像花园软管除了引导水流过它之外什么都不“做”。

    现在,将BehaviorSubject 简单地视为具有指定初始值的Subject


    使用 BehaviouralSubject 有什么真正的好处?使用数组更容易..

    使用BehaviorSubject 只是包含一个 Observable 流所需的几部分。

    可观察的流是异步的,并且会像广播电台一样向“收听”或subscribed的任何人进行自我更新。

    一个简单的数组显然有更简单的语法来存储和提取数据,但是一个数组不能在没有人工干预的情况下跨多个组件进行自我更新。这是 Observable 流的值。

    此外,BehaviorSubject 是私有的,因为一开始就不需要任何外部的东西直接访问它。外部组件只需要访问 Observable 流,而不是 BehaviorSubject 本身。如果组件有权访问流,则源与组件无关。最好将其保密,并在同一服务中提供一个函数来更新 BehaviorSubject 的值(如果需要)。


    例如..

    在服务中:

    import { Injectable } from '@angular/core';
    import { BehaviorSubject, Observable } from 'rxjs';
    
    @Injectable({ providedIn: 'root'})
    export class ExampleService {
      
      private exampleSource = new BehaviorSubject<any>(null);
      example$: Observable<any> = this.exampleSource.asObservable();
      
      updateSource(value: any) {
        this.selectedDateSource.next(value);
      }
    
    }
    

    我们定义了一个BehaviorSubject,初始值为null
    然后我们将example$ 定义为Observable(花园软管)以包含BehaviorSubject 发出的

    函数可以更新BehaviorSubject.next() 值,此时example$ 将通过流传输新值,每个subscription 将被动地看到它的新值。

    然后,在一个组件中:

    import { Component, OnInit } from '@angular/core';
    import { Observable } from 'rxjs';
    
    @Component({
      template: `
        <div>{{ exampleData$ | async }}</div>
      `,
    })
    export class ExampleComponent implements OnInit {
    
      exampleData$: Observable<any>;
    
      constructor(private exampleService: ExampleService) {}
    
      ngOnInit() {
        this.exampleData$ = this.exampleService.example$;
      }
    
    }
    

    此外,您可以手动 subscribe 到组件中的 observable,但是还有更多步骤需要执行,您还必须手动 unsubscribe 到 observable。
    此功能有效地包含在 Angular 的内置 async 管道中,用于上一个示例。

    此组件示例产生与上一个示例相同的结果:

    import { Component, OnInit, OnDestroy } from '@angular/core';
    import { Observable, Subscription } from 'rxjs';
    
    @Component({
      template: `
        <div>{{ exampleData }}</div>
      `,
    })
    export class ExampleComponent implements OnInit, OnDestroy {
    
      exampleData: any;
      exampleData$: Observable<any>;
      exampleDataSubscription: Subscription;
    
      constructor(private exampleService: ExampleService) {}
    
      ngOnInit() {
        this.exampleData$ = this.exampleService.example$;
        this.exampleDataSubscription = this.exampleData$.subscribe(data => {
    
          this.exampleData = data;  // <-- your data from the BehaviorSubject
    
        });
      }
    
      ngOnDestroy() {
        this.exampleDataSubscription.unsubscribe();
      }
    
    }
    

    希望这会有所帮助。

    【讨论】:

    • 好的。谢谢你。我明白了,这是有道理的。我现在可能会将一些与模板相关的变量更改为 Observables。但基本上 - 如果我的数组不在模板中,并且我没有以任何其他方式订阅它 - 保留数组是否有意义?
    • 这取决于您以后想如何使用它。如果您认为其他组件应该能够“监听”您的数组中的更改对您很重要,我会使用 observable。而且,如果您不在乎对数组所做的更改是否会传播到其他组件,是的,它可能只是一个数组。
    【解决方案2】:

    它是通过流来处理您的数据。在您的链接中,您可以看到他们正在使用 html 模板中的 async 管道来循环 todoStore.todo$,这实际上会导致订阅您的 observable。

    如果没有流(所以如果它是一个普通数组),即使您的 todoStoreService 更新了您的商店,您的 html 模板也不会更新,因为它不会收到更改数据的通知。

    这就是我的理解,不确定是否完全正确,但我认为这几乎就是这个例子中发生的事情。

    【讨论】:

    • 是的。确实如此。我不明白这一点。但是,如果我没有在模板中使用 'todos$' 或没有在其他任何地方订阅它 - 使用主题而不是数组有什么意义吗?
    • 在这种情况下,使用商店是没有意义的。想想你将如何使用你的数据。如果您需要将数据存储在服务中(因此它可以在您想要的任何地方使用),那么您不可能不需要检索它,而最好的方法是通过我认为的存储方法。也许您可以在您的问题中解释您的背景以及为什么需要存储数据以便答案更准确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-22
    • 2013-09-09
    • 2017-11-15
    相关资源
    最近更新 更多