可观察的异步与同步

Observable async vs sync

我如何知道 Observable 生产者是异步还是同步?

同步示例:

Observable.of([1, 2, 3])

另一个异步示例(ngrx 商店,参见

this.store.take(1);

现在是一个明显的异步示例:

this.http.get(restUrl)

我完全理解这是如何工作的,一些 Observables 可以是同步的,而另一些是异步的。我不明白的是我怎么能提前区分?例如,生产者上是否有一个明显的界面告诉我它将是异步的?

tl;博士

出现这个问题的主要原因是上面link的回答()。 @Sasxa 已经(正确地)回答说我们可以使用同步调用从 ngrx 存储中获取最新值:

function getState(store: Store<State>): State {
    let state: State;

    store.take(1).subscribe(s => state = s);

    return state;
}

但是知道可观察对象通常是异步的,我看到这个并立即想到了 RACE CONDITION!在 subscribe 回调函数之前,该方法可能 return 一个未定义的值。

我已经调试了 Store 和 Observable 的内部结构,这个例子确实是同步的,但我怎么知道呢?对于那些了解 ngrx 的人来说,storeselect 方法(用于获取最新值)毫无疑问是异步的,因为这就是给我们反应式 gui 的原因,这就是我来的原因我所做的假设。

也就是说我不能重构上面的代码如下:

function getLatest(observable: Observable): any {
    let obj: any;

    observable.take(1).subscribe(latest => obj = latest);

    return obj;
}

我可以用任何 Observable 调用它,它适用于同步生产者 - 它甚至可能在某些时候适用于异步生产者,但如果传入异步可观察者,这无疑是竞争条件。

很难确定您获得的可观察对象是同步的还是异步的(假设您从第三方库中获得可观察对象 return)。这就是为什么您以执行顺序受控且可预测的方式编写它的原因。

这也是为什么有诸如 concat、combineLatest、forkjoin、switchMap、race、merge 等运算符来帮助您针对不同场景获得正确的顺序和性能的原因

可以确定 observable 是否是异步的,以确定是否 直接 使用异步调度程序(Scheduler.asyncScheduler.asap)进行调度,它是公开的作为 foo$.scheduler:

let schedulers = [null, Scheduler.asap];
let randomScheduler = schedulers[~~(Math.random()*2)]
let foo$ = Observable.of('foo', randomScheduler);

foo$ 被进一步处理时,此信息变得更加不可用,例如与其他运算符链接。

并且无法确定值是同步(在同一刻度上)还是异步生成,因为这取决于可观察的内部结构:

let foo$ = new Observable(observer => {
  if (~~(Math.random()*2))
    setTimeout(() => observer.next('foo'));
  else
    observer.next('foo');
});

TL;DR: 不可能确定