在 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 的数量。