首页 > 解决方案 > 如何使用 rxjs 重试 http 请求直到满足条件

问题描述

我想重试一个 http 请求,直到某些数据最多存在 10 次,每次重试之间有 2 秒的延迟。

const $metrics = from(axios(this.getMetrics(session._id, sessionRequest._id, side)));

const res = $metrics.pipe(
  map((val: any) => {
    console.log("VALUE:", val.data.metrics.length);
    if (val.data.metrics.length === 0) {
      throw val;
    }
    return val;
  }),
  retryWhen((errors) => errors.pipe(delay(2000), take(10))),
).subscribe();

我正在尝试按照文档中的示例进行操作。https://www.learnrxjs.io/operators/error_handling/retry.html

  1. $metrics从 axios http 承诺创建 observable。
  2. 我使用 map 运算符来检查 http 请求的响应是否符合我的重试条件。val.data.metrics.length === 0. 如果确实如此,则会引发错误。
  3. 我重试 http 请求最多 10 次,延迟 10 秒。

我希望在此指标数组重试 3-4 次后有数据,但是在我的控制台中,当我记录响应时,我得到以下信息。

VALUE: 0

我不确定这是否甚至发出多个 http 请求,因为控制台日志只返回一个输出而不是 10。

更新

我已经更新了代码以使用 retryWhen 而不是重试,它会延迟 2 秒,并且在停止之前只需要 10 个错误。

现在我认为问题在于它只发出 1 个 http 请求,因为控制台日志只返回一个输出。

标签: node.jsrxjsrxjs6

解决方案


尝试使用 defer()

const $metrics = defer(()=>from(axios(this.getMetrics(session._id, sessionRequest._id, side))))

需要指出的一件事是,您应该检查您的网络选项卡,看看是否在重试中发出请求。您的 console.log 在 map() 运算符中,当抛出错误时将被跳过,这可能是您在那里看不到 console.log 的原因。你可以试试下面的例子。

import { timer, interval,from } from 'rxjs';
import { map, tap, retryWhen, delayWhen,delay,take } from 'rxjs/operators';

//emit value every 1s
const source = from(fetch('http://kaksfk')).pipe(tap(val => console.log(`fetcching you won't see`)))
const example = source.pipe(
  retryWhen(errors =>
    errors.pipe(
      // log error message
      tap(val => console.log(`retrying`)),
      // restart in 5 seconds
      delay(2000),
      take(5),
    ),
  ),
)

推荐阅读