在 rxjs 中使用 expand 进行轮询会产生意想不到的结果
Polling using expand in rxjs gives an unexpected result
我正在尝试使用 expand 设置轮询器,但行为不是我想要的
https://stackblitz.com/edit/rxjs-finalize-unsubscribe-6xy2yb?file=index.ts
checkExistence 产生一个随机布尔值 - 随着扩展,我期望递归延迟调用相同的 checkExistence 函数每 5 秒产生随机布尔值(在第一次调用后)。
我还希望停止在 30 秒后启动并停止轮询,并在 5 秒后恢复随机布尔流。任何指针都会有所帮助。
相反,我打印了相同的布尔值;同样在启动被触发后,它会一起生成一批布尔值。
这不是一个真正的问题。
Assignment/function 调用
一个简化的例子
等于运算符为变量赋值。函数调用returns 一个值
function inc(n){
return n + 1
}
const result = inc(5)
console.log(result); // 6
这里,结果保存数值6。不是计算5 + 1的函数。5 + 1在这里只发生一次。
现在考虑这个随机将数字递增 1 或 2 的函数
function bump(n){
const nu = Math.random();
return nu < 0.5 ? n + 1 : n + 2
}
const result = bump(5);
console.log(result); // 7
console.log(result); // 7
console.log(result); // 7
console.log(result); // 7
console.log(result); // 7
每次打印出来的结果都是一样的。 bump
只调用了一次,只生成了一次随机数。
function bump(n){
const nu = Math.random();
return nu < 0.5 ? n + 1 : n + 2
}
console.log(bump(5)); // 7
console.log(bump(5)); // 7
console.log(bump(5)); // 6
console.log(bump(5)); // 7
console.log(bump(5)); // 6
这里,bump
被调用了5次,每次都生成一个新的随机数。
修复 checkExistence
有两种方法。
- 而不是一次生成一个值并重新使用它。每次需要时在您的投票中生成一个新的布尔值。
function checkExistencePoll(): Observable<boolean> {
const POLL = 5000;
return checkExistence().pipe(
expand(_ =>
timer(POLL).pipe(
switchMap(() => checkExistence()),
takeUntil(stop),
repeatWhen(() => start)
)
)
);
}
- 有
checkExistence
return 一个在订阅时生成新布尔值的可观察对象
function checkExistence(): Observable<boolean> {
return defer(() => {
const nu = Math.random();
const rand = nu < 0.5;
console.log(nu, rand);
return of(rand);
});
}
处理订阅
在您的代码中,expand
正在生成一个订阅主题(称为 start
)的可观察对象,以便决定何时重复。 expand
创建的每个可观察对象都会这样做。因此,当 start
发出时,每个都会重复。您应该期望 batches 个布尔值等于您创建的并发 observables 的数量。
我正在尝试使用 expand 设置轮询器,但行为不是我想要的
https://stackblitz.com/edit/rxjs-finalize-unsubscribe-6xy2yb?file=index.ts
checkExistence 产生一个随机布尔值 - 随着扩展,我期望递归延迟调用相同的 checkExistence 函数每 5 秒产生随机布尔值(在第一次调用后)。
我还希望停止在 30 秒后启动并停止轮询,并在 5 秒后恢复随机布尔流。任何指针都会有所帮助。
相反,我打印了相同的布尔值;同样在启动被触发后,它会一起生成一批布尔值。
这不是一个真正的问题。
Assignment/function 调用
一个简化的例子
等于运算符为变量赋值。函数调用returns 一个值
function inc(n){
return n + 1
}
const result = inc(5)
console.log(result); // 6
这里,结果保存数值6。不是计算5 + 1的函数。5 + 1在这里只发生一次。
现在考虑这个随机将数字递增 1 或 2 的函数
function bump(n){
const nu = Math.random();
return nu < 0.5 ? n + 1 : n + 2
}
const result = bump(5);
console.log(result); // 7
console.log(result); // 7
console.log(result); // 7
console.log(result); // 7
console.log(result); // 7
每次打印出来的结果都是一样的。 bump
只调用了一次,只生成了一次随机数。
function bump(n){
const nu = Math.random();
return nu < 0.5 ? n + 1 : n + 2
}
console.log(bump(5)); // 7
console.log(bump(5)); // 7
console.log(bump(5)); // 6
console.log(bump(5)); // 7
console.log(bump(5)); // 6
这里,bump
被调用了5次,每次都生成一个新的随机数。
修复 checkExistence
有两种方法。
- 而不是一次生成一个值并重新使用它。每次需要时在您的投票中生成一个新的布尔值。
function checkExistencePoll(): Observable<boolean> {
const POLL = 5000;
return checkExistence().pipe(
expand(_ =>
timer(POLL).pipe(
switchMap(() => checkExistence()),
takeUntil(stop),
repeatWhen(() => start)
)
)
);
}
- 有
checkExistence
return 一个在订阅时生成新布尔值的可观察对象
function checkExistence(): Observable<boolean> {
return defer(() => {
const nu = Math.random();
const rand = nu < 0.5;
console.log(nu, rand);
return of(rand);
});
}
处理订阅
在您的代码中,expand
正在生成一个订阅主题(称为 start
)的可观察对象,以便决定何时重复。 expand
创建的每个可观察对象都会这样做。因此,当 start
发出时,每个都会重复。您应该期望 batches 个布尔值等于您创建的并发 observables 的数量。