Angular RxJS根据以前的结果订阅多个http请求的最佳实践

我想知道使用RxJS库执行3个http请求的最佳方法是什么,这些请求取决于之前的结果.

让我们假设我的Angular应用程序中有3个服务,每个服务都有一个函数get(id:number)用于订阅请求实体的可观察对象.

我需要通过使用第二个服务调用第一个服务的顺序来获取包含下一个调用所需的标识符的实体,该第二个服务还包含使用第三个服务进行下一次调用所需的标识符.

方法1:使用三个订阅并将每个结果设置为全局变量

const firstEntityId = 1;

this.firstService.get(firstEntityId)
  .subscribe((firstEntity: FirstEntity) => {
    this.firstEntity = firstEntity;

    this.secondService.get(firstEntity.secondEntityId)
      .subscribe((secondEntity: SecondEntity) => {
        this.secondEntity = secondEntity;

        this.thirdService.get(secondEntity.thirdEntityId)
          .subscribe((thirdEntity: ThirdEntity) => {
            this.thirdEntity = thirdEntity;

          });
      });
  });

方法2:使用带有流和一个订阅的函数来设置所有全局变量

const firstEntityId = 1;

this.getFirstSecondThird(firstEntityId)
  .subscribe(([firstEntity, secondEntity, thirdEntity]: [FirstEntity, SecondEntity, ThirdEntity]) => {
    this.firstEntity = firstEntity;
    this.secondEntity = secondEntity;
    this.thirdEntity = thirdEntity;
  });

getFirstSecondThird(id: number): Observable<[FirstEntity, SecondEntity, ThirdEntity]> {
  return this.firstService.get(id).pipe(
    switchMap((firstEntity: FirstEntity) => forkJoin(
      of(firstEntity),
      this.secondService.get(firstEntity.secondEntityId)
    )),
    switchMap(([firstEntity, secondEntity]: [FirstEntity, SecondEntity]) => forkJoin(
      of(firstEntity),
      of(secondEntity),
      this.thirdService.get(secondEntity.thirdEntityId)
    ))
  );
}

在这种情况下,使用流的方法是最快的吗?

有没有其他方法来编写我的函数getFirstSecondThird而不是使用switchMap和forkJoin方法?

(我见过combineLatest,但我没有找到如何传递前一个结果中的参数)

最佳答案 也许在方法1中使用map而不是订阅?

注意,您需要在所有嵌套级别返回.在示例中,我删除了括号,因此隐含了返回.

getFirstSecondThird(id: number): Observable<[FirstEntity, SecondEntity, ThirdEntity]> {
  return this.firstService.get(id).pipe(
    mergeMap((first: FirstEntity) => 
      this.secondService.get(first.secondEntityId).pipe(
        mergeMap((second: SecondEntity) => 
          this.thirdService.get(second.thirdEntityId).pipe(
            map((third: ThirdEntity) => [first, second, third])
          )
        )
      )
    )
  )
}

这是一个测试片段,

console.clear()
const { interval, of, fromEvent } = rxjs;
const { expand, take, map, mergeMap, tap, throttleTime } = rxjs.operators;

const firstService = (id) => of(1)
const secondService = (id) => of(2)
const thirdService = (id) => of(3)

const getFirstSecondThird = (id) => {
  return firstService(id).pipe(
    mergeMap(first => 
      secondService(first.secondEntityId).pipe(
        mergeMap(second => 
          thirdService(second.thirdEntityId).pipe(
            map(third => [first, second, third])
          )
        )
      )
    )
  )
}

getFirstSecondThird(0)
  .subscribe(result => console.log('result', result))
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.js"></script>

你可以使用switchMap()而不是mergeMap(),如果有可能第二次调用getFirstSecondThird()但是在第一次调用的所有提取完成之前,你想要丢弃第一个调用 – 例如在增量搜索方案.

点赞