【问题标题】:What are the differences between using a Subject and an Observable, and what are the uses for each?使用 Subject 和 Observable 有什么区别,各自的用途是什么?
【发布时间】:2018-08-25 05:31:10
【问题描述】:

我已经了解了两种不同的方法来制作 Observable。第一个是主题,如下所示:

// file A
const message$ = new Subject();

// file B
message$.subscribe( (message) => console.log(message) );

// file C
message$.next("Hello there!");

这种创建 Observable 的方法使我能够将数据从文件 B 交换到文件 C。

第二种方式是通过 Observable 类,像这样:

// file A
const click$ = new Observable( function(observer) { 
  //Alternatively, I can use Observable.create()
  document.addEventListener('click', (e) => observer.next(e));
});

// file B
click$.subscribe( (cl) => console.log(cl) );

我可以在 Subject 方式和 Observable 方式之间收集到的主要区别是,我不确定如何在某个文件 C 与 Observable 的订阅者之间进行某种通信。基本上,click$ 没有.next() 方法,观察者方法在我们传递给可观察对象的函数中。

除了这种行为差异之外,使用 Subject 制作的 observable 与使用 Observable 制作的 observable 之间是否还有其他差异

【问题讨论】:

    标签: javascript rxjs reactivex


    【解决方案1】:

    Subject 同时是 ObservableObserver。这使得使用它变得如此诱人,因为您获得了对 Observer 的引用,您可以在代码中传递并从任何您想要的地方发出项目。但是,当您从 Observable 的声明式定义切换到命令式定义时,这会大大增加代码的错误倾向。

    一般来说,您应该尽可能使用 Observable 创建函数(offromcreate)。我想说大多数情况可以在没有主题的情况下解决。但是有一个陡峭的学习曲线,因为您必须了解大多数 Observable 创建函数才能遵循该模式。

    对于习惯于命令式编码(即:使用像 JS 这样的脚本语言)的开发人员来说,Subject 可能更自然,因为它有点类似于回调函数的简单包装对象。有人可能会问,如果它不受欢迎,为什么还要有一个主题。

    根据article,主题只能在一种情况下使用:

    在没有任何直接外部源的情况下,命令式和有状态地生成热可观察对象。

    简而言之,这意味着:当您没有任何外部源(如 Observable、Promise 或 Event)并且需要从函数内部多播类的状态时,请使用 Subject。不过,您不应该将该主题暴露给其他人!

    我建议你读这篇文章,它会理清头绪。

    【讨论】:

    • 嗨!抱歉,您分享的链接似乎无法将您带到您想去的地方。它带你到http://%20to%20generate%20a%20hot%20observable%20imperatively%20and%20statefully,%20without%20any%20direct%20external%20source./
    【解决方案2】:

    Subject 同时实现了 Observable 和 Observer 接口。

    实现 Observable 接口意味着,除其他外,您可以subscribe 到主题。

    实现 Observer 接口意味着,除其他外,您可以使用 Subject 调用方法 next errorcomplete

    如果您想以编程方式控制该 Observable 的事件流,您可以使用 Subject 创建 Observable,这就是您提到的管理 CB之间的通信的情况>.

    【讨论】:

      【解决方案3】:

      SubjectObservable 之间的关系是这样的:

      class Observable {}
      
      class Subject extends Observable {}
      

      Subject 实现Subscriber 接口。所以你可以把Subject当作Subscriber使用(Observable不能这样使用):

      const subj = new Subject()
      observable.subscribe(subj)
      

      Subject可以通过调用asObservable方法隐藏它的Subscriber接口——把Subject变成普通的Observable;


      当我的代码要生成事件时,我通常使用Subject,当我已经有一些事件源时,我使用Observable

      例如使用 Subject 作为队列:

      const queue = new Subject();
      
      queue.pipe(
        concatMap(doStuff)
      ).subscribe()
      
      queue.next('do this')
      queue.next('do that')
      

      或者使用 Subject 作为信号器来阻止其他 Observable

      const stop = new Subject();
      
      someObservable.pipe(
        map(x => x + 1)
        takeUntil(stop)
      )
      
      // somewhere in my code
      stop.next()
      

      除了这种行为差异之外,使用 Subject 制作的 observable 与使用 Observable 制作的 observable 之间是否还有其他差异

      我不会说有区别 - 它更像是 Subject 是对普通 Observable 的补充 - 允许我们在需要时做更多的事情。

      【讨论】:

        猜你喜欢
        • 2018-05-12
        • 1970-01-01
        • 2017-02-23
        • 2018-08-02
        • 2016-09-18
        • 2016-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多