我正在编写一个游戏,角色可以在其中射击武器。 我希望玩家尝试射击时发生不同的事情,具体取决于他们是否有弹药。
我将问题简化为以下代码(顺便说一句,我不确定为什么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"
),这是有道理的,因为hasAmmo
是true
。但是,由于发出fire$
的副作用是分区条件的结果发生了变化,我想这使我得到了"bam"
。
我不应该引起影响partition()
的副作用吗?
或者我share()
父母可观察的方式是否存在问题?我可能是错的,但我会凭直觉认为fire$
和noAmmo$
在内部订阅父对象以进行拆分,在这种情况下share()
应该起作用?
答案 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
请注意,更改partition
对const 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
即可,这很明显: