在RxJS中,是否将Observer注入Observable执行中?

时间:2019-01-30 17:21:59

标签: javascript rxjs reactivex

我已经多次阅读ReactiveX文档,但仍然无法完全理解 Observer 订阅 Observable 时发生的情况。 / p>

让我们看一个简单的例子:

import { Observable } from 'rxjs'; 

const observable = new Observable(subscriber => {
  subscriber.next(1);
  subscriber.complete();
});

const observer = {
  next: (x) => console.log('got value ' + x),
  error: (err) => console.error('something wrong occurred: ' + err),
  complete: () => console.log('done')
};

observable.subscribe(observer);

StackBlitz code


我的问题:

传递给 Observable subscriber对象从哪里来?

来自RxJS documentation

  

observable.subscribesubscribe并非偶然   new Observable(function subscribe(subscriber) {...})具有相同的名称。   在库中,它们是不同的,但是出于实际目的,您可以   认为它们在概念上是平等的。

因此,显然,传递到 Observable 构造函数(subscriber中的 subscribe 回调中的对象不是实际上是{ {1}}对象。至少如果您按照上面的引言讲解该库的实际工作原理,就可以了。

如果传入的不是observer对象,那么observersubscriber.next(1)的调用到底是什么?如何连接到subscribe.complete()中的next属性?


澄清性修改:

我知道如何利用 RxJS ,并且确实可以从概念上想象 Observer 被注入(如引文所述)。但是,我在这里希望了解它实际上的工作原理。

2 个答案:

答案 0 :(得分:3)

Observable创建过程的流程如下:

作者定义了Observable(出于解释的目的,此处手动与new一起定义):

const myObservable = new Observable(function subscribe(subscriber) {
  subscriber.next(1);
  subscriber.next(2);
  subscriber.complete();
  return function tearDownLogic() {
    console.log('runs when Observable for whatever reason is done (complete, error, or unsubscribed)')
  }
});

传递给以上subscribe的{​​{1}}回调由Observable constructor在本地保存:

Observable

因此,我们保存了由我们或任何其他预制的constructor(subscribe?: (this: Observable<T>, subscriber: Subscriber<T>) => TeardownLogic) { if (subscribe) { this._subscribe = subscribe; } } 定义的整个subscribe函数,供以后执行。

可以以几种形式之一将 Observer 传递给Observable回调。直接作为一到三个函数( next error complete ),或者作为具有相同三种方法中的一种或多种的对象。为了便于说明,我们将实现最后一个更详细的选项:

subscribe

现在,有趣的部分开始了。我们将const observer = { next(v) { console.log(v); } error(err) { console.log(err); } complete() { console.log('Observable has now completed and can no longer emit values to observer'); } } 传递到observer方法中:

Observable.subscribe(..)

subscribe method看起来像这样:

myObserver.subscribe(observer);

简要描述了 subscribe(observerOrNext?: PartialObserver<T> | ((value: T) => void), error?: (error: any) => void, complete?: () => void): Subscription { const { operator } = this; const sink = toSubscriber(observerOrNext, error, complete); if (operator) { sink.add(operator.call(sink, this.source)); } else { sink.add( this.source || (config.useDeprecatedSynchronousErrorHandling && !sink.syncErrorThrowable) ? this._subscribe(sink) : this._trySubscribe(sink) ); } if (config.useDeprecatedSynchronousErrorHandling) { if (sink.syncErrorThrowable) { sink.syncErrorThrowable = false; if (sink.syncErrorThrown) { throw sink.syncErrorValue; } } } return sink; } 方法:

  1. 以先前讨论过的一种形式接收subscribe
  2. observer会将观察者转换为toSubscriber对象,无论其以何种形式传递(Subscriber实例都保存在Subscriber变量中)
  3. 注意:sink变量为operator,除非您预订了运营商。因此,只需忽略undefined周围的if语句
  4. operator扩展了Subscriber对象(与原型链接),该对象的原型具有两个重要方法:Subscriptionunsubscribe()
  5. add()用于向add(..)添加“ 拆解逻辑”(功能),当Observable 完成< / em>或取消订阅。它将采用传递给它的任何函数,将其包装在Observable对象中,然后将该函数放入Subscription的{​​{1}}变量中。此Subscription保存在我们上面创建的_unsubscribe上的变量Subscription中。如前所述,我们这样做是为了使Subscriber取消订阅完成时,所有由_subscriptions编辑的拆解逻辑执行
  6. 作为旁注,Subscriber返回add()实例。因此,您可以随时在其上调用Observable.subscribe()以添加将在Subscriber 完成退订
  7. 时执行的功能。
  8. 现在有一个重要的部分:mySubscriber.add( // some tear down logic)运行(在Observable内部,作为参数)。 this._trySubscribe(sink)是实际上运行add()构造函数保存的_trySubscribe(..)回调的函数。重要的是,它以subscribe回调的形式传入Observable(我们的新sink实例)。换句话说,当执行Subscriber中的Observable时,我们实际上是在subscriber.next(1)Observable)实例中执行next(1)sink是在Subscriber的原型上)。

现在,这使我到最后。除其他事项外,next()内和退订流程还有更多详细信息,但这些内容不在此问答中。

简而言之,要回答标题中的问题, Observer 实际上仅在转换为统一的Subscriber对象之后才传递到toSubscribe中。 / p>

希望这会在将来对其他人有所帮助。

答案 1 :(得分:2)

不,观察者没有被注入到可观察对象中。

AFAICT,这种困惑源自new Observable(...)语法更多的是底层工厂,而不是有用的模式。

或多或少是of(value1, value2, ..., valueN)from(enumeration)fromEvent(...)等更简单的实现所使用的机制。

这种方法是您应该重点关注的实际用例。

在幕后,所有这些方法都将某种同步或异步值或交互桥接到可观察流的奇妙世界。为此,它们以某种方式像适当的观察员那样行为:它们生成项目并将其放入流中。为此,他们使用了一个称为next的函数。就像Observer实现中的方法一样,实际上会以完全相同的方式调用bacause。

尤其是,您可以在此处查看subscription方法的实现:

https://github.com/ReactiveX/rxjs/blob/master/src/internal/Observable.ts

如果您想了解订阅期间实际发生的情况,建议您实际看一下代码。 但是,IMO,只有在熟悉了各种Observable创建功能之后,您才应该尝试。

希望有帮助。