Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/31.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
Javascript 无法将间隔设置为最长2分钟,或直到使用角度传感器满足条件_Javascript_Angular_Ionic Framework - Fatal编程技术网

Javascript 无法将间隔设置为最长2分钟,或直到使用角度传感器满足条件

Javascript 无法将间隔设置为最长2分钟,或直到使用角度传感器满足条件,javascript,angular,ionic-framework,Javascript,Angular,Ionic Framework,这里我的场景是,我有两个apiapiOne和apiTwo,当我调用apiOne时,应该给出响应,如果响应成功,那么我必须将此报告作为参数发送到apiTwo,然后apiTwo将给出另一个响应,我可能会得到如“已创建”、“正在进行”。问题就在这里 如何使用间隔每3秒调用APITOW,直到得到“正在进行”的响应,如果没有得到如上所述的响应,则需要轮询APITOW,直到最长2分钟,然后取消调用。如果我得到的响应为正在进行中,则我需要停止间隔或最多2分钟取消间隔或子描述 我已经用嵌套的方式编写了代码,但

这里我的场景是,我有两个apiapiOneapiTwo,当我调用apiOne时,应该给出响应,如果响应成功,那么我必须将此报告作为参数发送到apiTwo,然后apiTwo将给出另一个响应,我可能会得到如“已创建”、“正在进行”。问题就在这里

  • 如何使用间隔每3秒调用APITOW,直到得到“正在进行”的响应,如果没有得到如上所述的响应,则需要轮询APITOW,直到最长2分钟,然后取消调用。如果我得到的响应为正在进行中,则我需要停止间隔或最多2分钟取消间隔或子描述

  • 我已经用嵌套的方式编写了代码,但效率不高

  • 下面是我的代码

     initiate() {
        this.showProgress = true;
        
        const data = {
          id: this.id,
          info: this.Values.info,
        };
    
        // First Api call
        
        this.userServ.start(data).subscribe(res => {
         
          this.Ids = res['Id'];
          if (this.Ids) {
          
          
          // Second Api call
          
            this.Service.getStatus(this.Ids).subscribe(resp => {
    
              if (resp) {
                
                this.Status = res['Status'];
                
                // if resp is In_Progress
                
                if (this.Status === 'In_Progress') {
                  this.Start();
                } else {
    
                // if resp is not In_Progress then i get the response i am calling the api
                
                  this.intervalTimer = interval(3000).subscribe(x => {
    
                    this.Service.Status(this.Ids).subscribe(ress => {
                     
                      this.Status = ress['Status'];
                      if (this.Status === 'In_Progress') {
                        this.delayStart();
                        this.intervalTimer.unsubscribe();
                      }
                    });
                  });
    
                }
              }
    
            }, err => {
              console.log(err);
            });
          }
    
        }, error => {
          console.log(error);
        });
    
      }
    

    你可以考虑使用下面的方法

    然后,我们创建一个
    主题
    ,以帮助跟踪操作的进度。我使用BehaviorSubject将显示进度的初始值设置为true

    我们将使用
    currentStatus$
    存储当前状态是“正在进行”还是“已创建”

    停止$
    启动
    将控制我们的可观察流

    你可以看看下面的帖子

    接下来我们定义
    interval=500;//将3s和maxTrialTime=6000更改为3000;//更改为120000,持续2分钟

    然后,我们使用
    timer
    操作符定义一个
    timer$
    可观察的。运算符用于以固定间隔生成值流

    我们将延迟设置为
    0
    ,将间隔设置为先前创建的
    interval
    属性

    然后,我们将
    点击
    进入可观察的流。
    tap
    操作符允许我们在不改变可观察流的情况下执行操作

    在我们的tap操作符中,我们检查是否已达到最大时间,如果已达到,则调用
    stoppedSubject$
    上的下一个函数。我们将流输送到
    takeUntil(this.stopped$)
    停止流,并
    repeatWhen(()=>this.started$)
    重新启动流

      timer$ = timer(0, this.interval).pipe(
        tap((i) => {
          if(this.maxTrialTime/this.interval < i) { this.stoppedSubject$.next()}
        }),
        takeUntil(this.stopped$),
        repeatWhen(() => this.started$)
      )
    
    现在,我们终于将
    timer$
    apiTwoCall$
    mergeMap
    操作符
    trialCallsToApiTwo$=this.timer$.pipe(mergeMap(()=>this.apiTwoCall$)结合起来了。

    在HTML中,我们可以使用
    async
    管道来避免担心取消订阅

    {{ trialCallsToApiTwo$ | async }}
    

    我将使用rxjs中的
    展开
    ,它将传递源可观测的结果,但也让您根据结果的内容进行操作

    此外,尽可能避免嵌套调用
    subscribe
    。考虑下面的示例代码:

    this.userServ.start(data).pipe(
      // use switchMap to not have 'nested' subscribe-calls
      switchMap((result) => {
        if (result['Id']) {
          // if there is an ID, ask for the status
          return this.Service.getStatus(result['Id']).pipe(
            // use the expand operator to do additional processing, if necessary
            expand((response) => response['Status'] === 'In_Progress'
              // if the status is 'In_Progress', don't repeat the API call
              ? EMPTY
              // otherwise, re-run the API call
              : this.Service.getStatus(result['Id']).pipe(
                // don't re-run the query immediately, instead, wait for 3s
                delay(3000)
              )
            ),
            // Stop processing when a condition is met, in this case, 60s pass
            takeUntil(timer(60000).pipe(
              tap(() => {
                // handle the timeout here
              })
            ))
          );
        } else {
          // if there is no ID, complete the observable and do nothing
          return EMPTY;
        }
      }),
      /**
       * Since expand doesn't filter anything away, we don't want results that
       * don't have the status 'In_Progress' to go further down for processing
       */
      filter((response) => response['Status'] === 'In_Progress')
    ).subscribe(
      (response) => {
        this.Start();
      }, (error) => {
        console.log(error)
      }
    );
    

    我认为在设定的时间间隔后调用api会给应用程序和网络带来很大的开销。这对你有帮助吗@ChetanBansal不,这是一个不同的例子,我的情况不同。可能需要解释一下,因为你正在用观测值轰炸OP。@Robinijkhof好的,会用解释更新我的答案的
    showProgressSubject$ = new BehaviorSubject(true);
    showProgressAction$ = this.showProgressSubject$.asObservable();
    currentStatus$ = this.currentStatusSubject$.asObservable()
    stoppedSubject$ = new Subject();
    stopped$ = this.stoppedSubject$.asObservable();
    startedSubject$ = new Subject();
    started$ = this.startedSubject$.asObservable();
    
      timer$ = timer(0, this.interval).pipe(
        tap((i) => {
          if(this.maxTrialTime/this.interval < i) { this.stoppedSubject$.next()}
        }),
        takeUntil(this.stopped$),
        repeatWhen(() => this.started$)
      )
    
    apiOneCall$ = this.userServ.start(this.data);
    apiTwoCall$ = this.apiOneCall$.pipe(
      switchMap(({Id}) => Id ? this.Service.getStatus(Id): throwError('No Id')),
      tap((res) => this.currentStatusSubject$.next(res)),
      tap(res => console.log({res})),
      tap((res) => {if(res === 'created') {this.stoppedSubject$.next()}}) 
    )
    
    {{ trialCallsToApiTwo$ | async }}
    
    this.userServ.start(data).pipe(
      // use switchMap to not have 'nested' subscribe-calls
      switchMap((result) => {
        if (result['Id']) {
          // if there is an ID, ask for the status
          return this.Service.getStatus(result['Id']).pipe(
            // use the expand operator to do additional processing, if necessary
            expand((response) => response['Status'] === 'In_Progress'
              // if the status is 'In_Progress', don't repeat the API call
              ? EMPTY
              // otherwise, re-run the API call
              : this.Service.getStatus(result['Id']).pipe(
                // don't re-run the query immediately, instead, wait for 3s
                delay(3000)
              )
            ),
            // Stop processing when a condition is met, in this case, 60s pass
            takeUntil(timer(60000).pipe(
              tap(() => {
                // handle the timeout here
              })
            ))
          );
        } else {
          // if there is no ID, complete the observable and do nothing
          return EMPTY;
        }
      }),
      /**
       * Since expand doesn't filter anything away, we don't want results that
       * don't have the status 'In_Progress' to go further down for processing
       */
      filter((response) => response['Status'] === 'In_Progress')
    ).subscribe(
      (response) => {
        this.Start();
      }, (error) => {
        console.log(error)
      }
    );