2

我有一个角度函数,它返回状态为“继续”或“完成”的数据集。我想继续拨打电话,直到状态返回“完成”,但最多只能持续一分钟。我怎样才能在角度实现这一点

public getLeadsResponse(key: any) {
    this._service.getLeadsData(key).subscribe((response: any) => {
        if (response) {
            if (response.payload.status == "running") {
    // here if i repeate this function it will start an infinite loop if status is always "running"
                this.getLeadsResponse(key);
            }
            else if (response.payload.status == "finished") {
                this.items = res.payload.result;
            }
        }
    })
}
4

3 回答 3

2

您可以使用expand()

import { of, EMPTY, timer } from 'rxjs'; 
import { expand, map, filter, takeUntil } from 'rxjs/operators';

const makeHttpRequest$ = timer(1000).pipe(map(() => Math.random() > 0.9 ? 'finished' : 'continue'));

const source = of(null).pipe(
  expand(value => value === 'finished' ? EMPTY : makeHttpRequest$),
  filter(value => value !== null), // Ignore the first `of(null)` that triggered the chain.
  takeUntil(timer(60 * 1000)),
);

source.subscribe(console.log);

现场演示:https ://stackblitz.com/edit/rxjs-8n11jj?devtoolsheight=60

于 2021-01-20T08:41:34.463 回答
1

除了@martin 的回答,您还可以使用 RxJStimestamp运算符对 1 分钟的时间进行显式检查。

我已经使用 RxJStimer发出每个“n”个时间单位并切换到 HTTP 请求,因为它的每个发出使用switchMap运算符。

尝试以下

import { timer } from "rxjs";
import { filter, map, timestamp, switchMap } from "rxjs/operators";

public getLeadsResponse(key: any) {
  const now = Date.now();

  const subscription = timer(0, 6000).pipe(  // <-- adjust polling frequency
    switchMap(_ => this._service.getLeadsData(key)),
    timestamp(),
    map((data: { timestamp: number; value: any }) => {
      if (data.timestamp - now < 60000) {               
        return data.value;
      } else {
        subscription.unsubscribe();  // <-- close subscription if 1 min has elapsed
      }
    }),
    filter(response => response.payload.status == "finished")
  ).subscribe({
    next: response => {
      this.items = res.payload.result;
      subscription.unsubscribe();  // <-- close subscription if status is "finished"
    },
    error: error => {
      // handle error
    }
  });
}
于 2021-01-20T08:47:56.287 回答
0

我认为您只能在 ajax 查询中添加超时,如果发生这种情况,它将“中断”与服务器的连接。因此,您将无法测试有效负载结果值。

您可以通过其他方式实现所需的行为:

  • 使您的后端进程异步,所以您可以执行 ajax 查询让每 5 秒检查一次以检查当前状态,并且您到达的路线必须快速响应并且只是“检查操作状态”。然后 1 分钟最大检查逻辑将在您的前端应用程序中

  • 打开一个能够发送多条消息的长轮询连接,例如 SSE

  • 使用 websocket 做同样的事情。

在所有情况下,真正的设计是您的后端服务器操作必须是异步的,并且它可以将其当前状态传达给另一个进程/线程。

请注意,在设计 api 的某些时候,您最终会做这种事情。在项目中添加一些异步处理并不像做简单的长查询那样容易并增加项目的复杂性,但它有一些好处,例如不会超载服务器,让用户界面更具反应性。

于 2021-01-20T07:43:38.887 回答