RxJS在分区子可观察项之间共享父可观察项

时间:2018-11-01 17:46:19

标签: javascript rxjs observable

我正在编写一个游戏,角色可以在其中射击武器。 我希望玩家尝试射击时发生不同的事情,具体取决于他们是否有弹药。

我将问题简化为以下代码(顺便说一句,我不确定为什么SO的摘要功能不起作用,所以我制作了CodePen,可以在这里试用我的代码)。

const { from, merge } = rxjs;
const { partition, share, tap } = rxjs.operators;

let hasAmmo = true;
const [ fire$, noAmmo$ ] = from([true]).pipe(
  share(),
  partition(() => hasAmmo),
);


merge(
  fire$.pipe(
    tap(() => {
      hasAmmo = false;
      console.log('boom');
    }),
  ),
  noAmmo$.pipe(
    tap(() => {
      console.log('bam');
    }),
  )
).subscribe({
  next: val => console.log('next', val),
  error: val => console.log('error', val),
  complete: val => console.log('complete', val),
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.js"></script>

运行此代码时,我得到以下信息:

"boom"
"next" true
"bam"
"next" true
"complete" undefined

我不明白为什么会得到"bam"

第一个发射到达fire$(我得到一个"boom"),这是有道理的,因为hasAmmotrue。但是,由于发出fire$的副作用是分区条件的结果发生了变化,我想这使我得到了"bam"

我不应该引起影响partition()的副作用吗?

或者我share()父母可观察的方式是否存在问题?我可能是错的,但我会凭直觉认为fire$noAmmo$在内部订阅父对象以进行拆分,在这种情况下share()应该起作用?

1 个答案:

答案 0 :(得分:2)

它实际上可以正常工作。困惑来自Bitmap bmp = GetMetaImageFromClipboard(); bmp.Save(path);运算符,它实际上只是two filter operators

如果不使用def doPCA(pairs, embedding, num_components = 10): matrix = [] for a, b in pairs: center = (embedding.v(a) + embedding.v(b))/2 matrix.append(embedding.v(a) - center) matrix.append(embedding.v(b) - center) matrix = np.array(matrix) pca = PCA(n_components = num_components) pca.fit(matrix) # bar(range(num_components), pca.explained_variance_ratio_) return pca 进行重写,则它看起来像这样:

partition

请注意,更改partitionconst fire$ = from([true]).pipe( share(), filter(() => hasAmmo), ); const noAmmo$ = from([true]).pipe( share(), filter(() => !hasAmmo), ); 本身没有影响。 hasAmmo仅在从其源Observable接收到值时起作用。

以后使用partition时,它将对具有两个不同partition的两个完全不同的链进行两个单独的预订。这意味着merge()会同时传递到from([true])true

因此fire$在这里无效。如果要共享它,则必须先将noAmmo$包装在share()from上,然后再使用。如果源Observable仅是fire$,那么它会更加令人困惑,因为初始发射只会到达第一个订阅者,而第一个订阅者在noAmmo$中使用时晚于from

fire$

为什么您同时收到两条消息是merge不会修改传递的值。它仅决定返回的Observable中的哪一个将重新发射它。

顺便说一句,宁愿完全避免使用const shared$ = from([true]).pipe( share(), ); const fire$ = shared$.pipe(...); const noAmmo$ = shared$.pipe(...); ,因为它可能会被弃用,而只需使用partition即可,这很明显: