可观察的异步与同步
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 的人来说,store
的 select
方法(用于获取最新值)毫无疑问是异步的,因为这就是给我们反应式 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.async
或 Scheduler.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: 不可能确定。
我如何知道 Observable 生产者是异步还是同步?
同步示例:
Observable.of([1, 2, 3])
另一个异步示例(ngrx 商店,参见
this.store.take(1);
现在是一个明显的异步示例:
this.http.get(restUrl)
我完全理解这是如何工作的,一些 Observables 可以是同步的,而另一些是异步的。我不明白的是我怎么能提前区分?例如,生产者上是否有一个明显的界面告诉我它将是异步的?
tl;博士
出现这个问题的主要原因是上面link的回答(
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 的人来说,store
的 select
方法(用于获取最新值)毫无疑问是异步的,因为这就是给我们反应式 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.async
或 Scheduler.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: 不可能确定。