Angular ForkJoin中的计时器

Angular ForkJoin中的计时器,angular,rxjs,rxjs6,Angular,Rxjs,Rxjs6,我有一个带有3个GET调用的API 获取环境 获得产品 获取特定环境中特定产品的状态 我试图做的是每5分钟轮询一次每个环境中每个产品的状态,以便在刷新的表中显示数据 获取环境和产品的调用应该执行一次,因为这是静态信息 let envs = this.http.get('http://my-api/envs); let products = this.http.get('http://my-api/products); forkJoin([envs, products]).subscribe(r

我有一个带有3个GET调用的API

  • 获取环境
  • 获得产品
  • 获取特定环境中特定产品的状态
  • 我试图做的是每5分钟轮询一次每个环境中每个产品的状态,以便在刷新的表中显示数据

    获取环境和产品的调用应该执行一次,因为这是静态信息

    let envs = this.http.get('http://my-api/envs);
    let products = this.http.get('http://my-api/products);
    
    forkJoin([envs, products]).subscribe(results => {
      //the code below should be executed every 5 mins and store the results in array
      results[0].forEach(env => {
        results[1].forEach(product => {
          this.http.get('http://my-api/status/${env}/${product}')
        })
      })
    })
    

    任何帮助都将不胜感激。

    不确定这能实现什么,但它每五分钟在订阅中运行一次代码。更准确地说,它每5分钟调用一次
    forkJoin
    。如果执行
    forkJoin
    所需的时间可变,则可能会使时间偏移一点。否则,您可以提前调用forkJoin并使用
    delay
    Date()上的一些数学运算将结果延迟到五分钟

    const五分钟=1000*60*5;
    计时器(0,5分钟)。管道(
    开关映射(=>forkJoin({
    envs:this.http.get('http://my-api/envs'),
    产品:this.http.get('http://my-api/products')
    }))
    ).subscribe({envs,products})=>{
    环境forEach(环境=>{
    products.forEach(产品=>{
    //这个http调用没有任何作用?
    this.http.get('http://my-api/status/${env}/${product}')
    })
    })
    });
    
    更新#1:最后呼叫的间隔。 这个调用您的
    This.http.get('http://my-api/status/${env}/${product}')
    每5分钟调用一次,并将结果作为数组发送到订阅

    由于明显的原因,没有对其进行测试。但它应该提供一个良好的起点

    const五分钟=1000*60*5;
    分叉连接({
    envs:this.http.get('http://my-api/envs'),
    产品:this.http.get('http://my-api/products')
    }).烟斗(
    地图({env,products})=>
    envs.map(env=>
    products.map(product=>
    this.http.get('http://my-api/status/${env}/${product}')
    )
    ).flat()
    ),
    合并映射(statusCalls=>timer(0,5分钟)。管道(
    合并映射(=>forkJoin(statusCalls))
    ))
    ).订阅(statusCallsResults=>{
    //**使用结果更新视图**//
    })
    
    如果您确实希望按照之前的设置订阅,则可能如下所示:

    const五分钟=1000*60*5;
    分叉连接({
    envs:this.http.get('http://my-api/envs'),
    产品:this.http.get('http://my-api/products')
    }).烟斗(
    合并映射(res=>计时器(0,5分钟)。管道(
    映射(=>res)
    ))
    ).subscribe({envs,products})=>{
    //这是每五分钟一次
    环境forEach(环境=>{
    products.forEach(产品=>{
    //这个http调用没有任何作用?
    this.http.get('http://my-api/status/${env}/${product}')
    })
    })
    });
    
    更新#2:错误处理
    forkJoin
    将在其任何内部观察失败时失败。你可以用很多方法来处理这个问题。最基本的方法是将出错的流转换为发出null并成功完成的流。然后,forkJoin在每个数组位置都将有
    null
    ,并且有一个错误

    可能是这样的:

    const五分钟=1000*60*5;
    分叉连接({
    envs:this.http.get('http://my-api/envs'),
    产品:this.http.get('http://my-api/products')
    }).烟斗(
    地图({env,products})=>
    envs.map(env=>
    products.map(product=>
    this.http.get('http://my-api/status/${env}/${product}')管道(
    catchError(err=>of(null))
    )
    )
    ).flat()
    ),
    合并映射(statusCalls=>timer(0,5分钟)。管道(
    合并映射(=>forkJoin(statusCalls))
    ))
    ).订阅(statusCallsResults=>{
    //**使用结果更新视图**//
    })
    
    错误代码500不是很具有描述性。当请求失败时,您可以查看重试操作符以重试请求。可与
    catchError
    组合使用


    不从服务器获取该错误首先取决于您。

    您可以将
    forkJoin
    包装在
    setInterval(()=>{},300000)中保存对变量的setInterval调用,以便在需要时取消它。(否则,如果前一次通话尚未结束,通话可能会堆积起来,但5分钟后可能永远不会发生…)谢谢。正如您提到的,这段代码每5分钟调用一次
    forkJoin
    ,但我不希望这样。我只想调查一下情况,就这样。因为环境和产品是一种静态信息,但是状态可能会随着时间的推移而改变,所以我们进行了一次更新,每5分钟只进行一次状态呼叫。这非常有帮助,谢谢!有一件事,我在flat()中得到了一个错误,你是说flatMap吗?只是将结果数组展平,因为它是嵌套的。您可以在此处检查兼容性,如果愿意,可以使用另一种方法:举个例子,这里有一个stackblitz和Observable: