Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 轮询服务,直到在特定时间段后收到响应或超时_Angular_Typescript_Rxjs_Angular8 - Fatal编程技术网

Angular 轮询服务,直到在特定时间段后收到响应或超时

Angular 轮询服务,直到在特定时间段后收到响应或超时,angular,typescript,rxjs,angular8,Angular,Typescript,Rxjs,Angular8,要求 呼叫服务 如果该服务返回数据,则将数据设置为变量。功能结束 如果该服务返回data=null,则每隔20秒重复调用该服务,直到它返回data=“列表或对象”或调用该服务2分钟并停止 我尝试的 需要每隔20秒轮询此服务getUrlById(id),直到我在this.url中得到响应或在6分钟后超时 尝试了以下解决方案,但未按预期工作 pollUrl(id) { interval(2000).pipe( timeout(600000), takeWhile(()

要求 呼叫服务

如果该服务返回数据,则将数据设置为变量。功能结束

如果该服务返回data=null,则每隔20秒重复调用该服务,直到它返回data=“列表或对象”或调用该服务2分钟并停止

我尝试的 需要每隔20秒轮询此服务getUrlById(id),直到我在this.url中得到响应或在6分钟后超时

尝试了以下解决方案,但未按预期工作

pollUrl(id) {
    interval(2000).pipe(
      timeout(600000),
      takeWhile(() => this.url)
    ).subscribe(i => {
      this.service.getUrlById(id).subscribe(res =>{
        if(res && res["result"]){
          this.url = res["result"];
        }
      })
      })
  }
从我尝试的评论中

在此处调用了虚拟服务

这里,虚拟服务返回data=null。所以根据要求,我需要每隔20秒打一次电话,直到2分钟。这是行不通的


没有必要使用此代码,我希望达到要求。可以有不同的方法。

只需使用
find
操作符(找到通过某个测试的第一个值并发出该值),这样
getUrlById
返回的可观察值在
响应后立即完成。结果定义如下所示:

interval(2000)
  .pipe(
    exhaustMap(() => this.service.getUrlById(id)), // <== switch subscription to `getUrlById` 
    find(x => x && x.result && x.result.length > 0),
    timeout(6 * 60 * 1000)
  )
  .subscribe(i => { })

您是否尝试过使用RetryWhen操作符

比如:(链接:)


首先,在这种情况下,
timeout
操作符是多余的。如果源在
600000
ms内没有发射,则应该抛出错误,但这永远不会发生,因为源将每隔
2000
ms发射一次

考虑到这一点,我的方法如下:

间隔(2000)。管道(
switchMap(id=>this.service.getUrlById(id)),
过滤器(res&&res[“结果”]),
//如果我们得到响应->停止轮询
第一个(),
//如果我们在600000毫秒->停止轮询中没有得到响应
takeUntil(计时器(600000)),
)

它以前不起作用,可能是因为
takeWhile(()=>this.url)
是在
this.url
被填充之前到达的,这意味着当调用
takeWhile
的回调函数时,
this.url
未定义的(
任何虚假值),因此,整个流应该已经完成。

每当出现轮询时,通常需要使用
expand
操作符,原因之一是它可以排除请求占用的时间超过您的轮询周期,并且您会同时收到两个请求的情况。差不多

const api$ = this.service.getUrlById(id);

api$.pipe(
    expand(x => x && x.result && x.result.length > 0 ? EMPTY : api$.pipe(delay(2000))),
    last(), // get the result
    timeout(6 * 60 * 1000)
)
.subscribe(i => { })
of(undefined).pipe(
  expand((result) =>
    result === undefined
      ? this.service.getUrlById(id).pipe(
          map((data) => data?.result),
          switchMap((result) =>
            result !== undefined
              ? of(result)
              : of(undefined).pipe(delay(20000)),
          ),
        )
      : EMPTY,
  ),
  filter((result) => result !== undefined),
  timeout(600000),
);

查找(x=>x?.result)-此行抛出以下错误。类型“Object”上不存在属性“result”。运行ng serve时ts(2339)查找((x:any)=>x?.result)错误。错误TS1109:应为表达式。src/app/register.component.ts(420,31):错误TS1005:“:”应为。i「wdm」:编译失败。请参阅我的更新,事实上
getUrlById
应返回实际类型,而不是返回类型
object
find((x:any)=>x?.result)。这是来自更新。为什么这行有错误。“:”预期编译失败。我怀疑链接运算符在angular 8中不起作用(不确定),请查看我的更新。我可以在某个时候将值res[“result”]保存到this.url变量吗?@user630209是的,只需在
过滤器()之后添加一个
点击(res=>this.url=res[“result”])
为什么要先使用
文件管理器
+
查找
可用?@RafiHenig感谢您指出,它们可以互换使用,尽管每个都可以扩展到其他用例。例如,使用
find
可以选择仅返回值上调用的cb返回true的索引
first
可以有默认值,而find没有默认值。
“在这种情况下,超时运算符是多余的。如果源在600000毫秒内没有发射,则应该抛出错误,但这永远不会发生,因为源将每2000毫秒发射一次。
”这不是真的,因为filter/find将过滤不需要的值。
@user630209
请参阅我的更新如果响应数据为空,服务需要再次调用。这不起作用。状态:429,状态文本:“太多请求”由于出现错误,可观察到的停止
of(undefined).pipe(
  expand((result) =>
    result === undefined
      ? this.service.getUrlById(id).pipe(
          map((data) => data?.result),
          switchMap((result) =>
            result !== undefined
              ? of(result)
              : of(undefined).pipe(delay(20000)),
          ),
        )
      : EMPTY,
  ),
  filter((result) => result !== undefined),
  timeout(600000),
);