Rxjs 轮询请求成功后再发送新的请求,直到得到需要状态为止?

  1. 使用rxjs,轮询请求A
  2. A的返回结果中有个finished字段,值为true或者false
    问题:
    当上一个A请求完成后,再发送下一个A请求,直至finished字段值为true后,不再轮询
阅读 2.6k
2 个回答

原理就是把 A 请求的 observable 进行一个转换,如果没有 finished 字段,转换为一个报错的 observable, 如果有 finished 字段,则原样返回,然后加一个 retry() 操作符,
代码如下:

import { Observable, throwError, from, mergeMap, retry, of, tap } from 'rxjs';

let num = 1;
const mockAjax = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (num === 5) {
        reject(new Error('http error'));
        // resolve({ status: 'pending', value: num++ });
      } else if (num < 10) {
        resolve({ status: 'pending', value: num++ });
      } else {
        resolve({ status: 'finished', value: num++ });
      }
    }, 1000);
  });
};

const $observable = new Observable((subscriber) => {
  mockAjax().then(
    (data) => {
      subscriber.next(data);
    },
    (err) => {
      subscriber.error(err);
    }
  );
});

const $ajax = $observable.pipe(
  tap((val) => console.log(val)),
  mergeMap((x: any) =>
    x.status === 'finished' ? of(x) : throwError(() => new Error(`pending`))
  ),
  retry({
    delay(error) {
      if (error.message === 'pending') {
        return timer(0);
      } else {
        return throwError(() => error);
      }
    },
  })
);
$ajax.subscribe({
  next: (x) => console.log('Observer got a next value: ' + JSON.stringify(x)),
  error: (err) => console.error('Observer got an error: ' + err),
  complete: () => console.log('Observer got a complete notification'),
});

在线查看:https://stackblitz.com/edit/r...

...
constructor(private http: HttpClient){};

this.http.get('http://localhost:8000/api/user').pipe(
      switchMap((x: any) => {
        if (!(x?.age > 50)) {
          throw 'Continue';
        }
        return of(x);
      }),
      catchError((err, caught) => {
        if (err === 'Continue') {
          return caught;
        } else {
          return of(err);
        }
      })
    ).subscribe({
      next: (x) =>
        console.log('Observer got a next value: ' + JSON.stringify(x)),
      error: (err) => console.error('Observer got an error: ' + err),
      complete: () => console.log('Observer got a complete notification'),
    });

使用catchError的第二个参数实现retry的效果
之所以不使用retry,是因为使用抛错的形式轮询请求,当面临网络断开或者服务器挂了等情况的时候,retry是继续疯狂请求,而采用return caught的方式则不会
ps: 这种方式适合题中的场景,具体情况具体分析
@杨军军 欢迎大佬指正

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏