我如何只调用这么多时间的可观察服务并且直到满足某个条件的时间间隔

Posted

技术标签:

【中文标题】我如何只调用这么多时间的可观察服务并且直到满足某个条件的时间间隔【英文标题】:How do I call observable service for only so many time AND until a certain condition is met with an interval 【发布时间】:2021-12-24 23:56:46 【问题描述】:

我希望能够:

    仅调用服务 30 次或直到满足特定条件。

    并且它必须每 5 秒调用一次

    如果可能的话,如果我在订阅中只看到一个 console.log,那就太好了。

在这种情况下,让我们说直到精度小于 50。我盯着下面的代码,很快就超出了调用堆栈。有人可以帮助一些真实的代码吗?当我自己寻找答案时,我把这个问题放在这里。如果我消除我的无知,我会发布答案。我显然在这里不合我意,但我会尝试自己解决这个问题

public randomExample() 

    this.randomNumber().pipe(
      map((n) => 
        console.log('map', n);
        if (n.accuracy > 50) 
          throw n;
        
        return n;
      ),
      retryWhen(e =>
        e.pipe(
          tap(n => console.log('value to high', n))
        )),
      delayWhen(n => timer(5000))
    ).subscribe((n) => 
      console.log('subscribed', n);
    )

  

  public randomNumber(): Observable<accuracy:number> 
    const n =Math.floor(Math.random() * 100)
    let value = accuracy:n
    return of(value);
  

【问题讨论】:

【参考方案1】:

您可以使用takeWhile检查索引和值,然后switchMap调用您的API:

public randomExample() 
  interval(500)
    .pipe(
      switchMap(() => this.randomNumber()),
      takeWhile((n, index) => index < 30 && n.accuracy >= 50, true),
      switchMap(n => 
        // Call API and return observable
      ),
    )
    .subscribe(n => 
      console.log('subscribed', n)
    )

【讨论】:

【参考方案2】:
function randomNumber():  accuracy: number  
  const n = Math.floor(Math.random() * 100);
  let value =  accuracy: n ;
  return value;

interval(5000)
  .pipe(
    scan((acc, curr) => acc + 1, 0),
    takeWhile((count) => count <= 30),
    map(() => randomNumber()),
    // tap((val) => console.log(val.accuracy)),
    takeWhile((val) => val.accuracy < 50),
    switchMap(() => of(Math.random() * 100).pipe(catchError(() => EMPTY)))
  )
  .subscribe((res) => 
    console.log("subscribed", res);
  );

    Interval 每 5 秒调用一次。

    scan 是一个累加器,它在每个间隔发出时累积计数。

    takeWhile 只要计数超过 30 就会自动退订。

    takeWhile 将保持此间隔有效,直到 randomNumber 生成器给出

    如果由于任何情况没有取消订阅,我们通过 switch map 调用我们的 api,如果 API 给出错误,我们通过 catch 错误回调返回一个 EMPTY observable,以便继续轮询。

    只有在 api 调用完成时才会到达订阅块。

工作链接:-https://codesandbox.io/s/falling-flower-nblzz?file=/src/index.ts:219-726

如果您想将 randomNumber 保持为可观察:-

function randomNumber(): Observable< accuracy: number > 
  const n = Math.floor(Math.random() * 100);
  let value =  accuracy: n ;
  return of(value);

interval(5000)
  .pipe(
    scan((acc, curr) => acc + 1, 0),
    takeWhile((count) => count <= 30),
    mergeMap(() => randomNumber()),
    takeWhile((val) => val.accuracy < 50),
    switchMap(() => of(Math.random() * 100).pipe(catchError(() => EMPTY)))
  )
  .subscribe((res) => 
    console.log("subscribed", res);
  );

工作链接:- https://codesandbox.io/s/wonderful-hill-mtxi5?file=/src/index.ts:220-701

【讨论】:

现在要试试这个。如果它有效,我会赞美你的名字!!! 请用更多上下文注释您的代码或在您的答案中添加一些解释。 @Eldar 添加了上面的解释。 我现在正在尝试,记住我的值是一个对象,所以我必须做 val.accuracy 它会调查你对@Maccurt 的期望吗?

以上是关于我如何只调用这么多时间的可观察服务并且直到满足某个条件的时间间隔的主要内容,如果未能解决你的问题,请参考以下文章

Mongo在Meteor Server上插入后如何等待观察者调用

使用jasmine.SpyObj-Angular / Jasmine测试服务属性上的可观察对象

如何对服务中的 BehaviorSubject 变量进行单元测试,它是组件中的可观察对象

KnockoutJS - 可观察对象的可观察数组,包含来自 SQL 服务器的数据

如何将 TabControl 的项目绑定到 wpf 中的可观察集合?

BugKu 杂项-这么多数据包