MST

星途 面试题库

面试题:Angular HttpClient模块异步请求与RxJS高级操作符优化

在一个复杂的Angular应用中,有一系列相互依赖的异步请求通过HttpClient模块发送。例如,第一个请求获取用户信息,第二个请求根据用户信息中的某个字段获取用户的详细权限,第三个请求基于权限获取用户可访问的数据列表。要求使用RxJS的高级操作符(如`concatMap`、`switchMap`等)来优化这些请求,确保请求顺序正确且高效,同时要处理可能出现的错误。请详细描述实现方案并给出完整代码。
35.3万 热度难度
前端开发Angular

知识考点

AI 面试

面试题答案

一键面试

实现方案描述

  1. 使用 concatMap 操作符concatMap 操作符会按照顺序处理 Observable 发出的值,并将每个值映射为一个新的 Observable,只有当前面的 Observable 完成时,才会处理下一个。这确保了请求按顺序执行。
  2. 错误处理:使用 catchError 操作符来捕获每个请求过程中可能出现的错误,在捕获到错误后,可以选择合适的处理方式,比如返回一个默认值或者重新抛出错误。

完整代码示例

假设我们有一个服务类 UserService 来处理这些请求:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { catchError, concatMap, map, Observable, of } from 'rxjs';

interface User {
  id: number;
  name: string;
  // 假设权限字段
  permissionField: string;
}

interface Permission {
  // 权限相关的字段
  accessLevel: string;
}

interface DataList {
  data: string[];
}

@Injectable({
  providedIn: 'root'
})
export class UserService {
  constructor(private http: HttpClient) {}

  getUserInfo(): Observable<User> {
    return this.http.get<User>('/api/user-info');
  }

  getPermissions(user: User): Observable<Permission> {
    return this.http.get<Permission>(`/api/permissions/${user.permissionField}`);
  }

  getAccessibleData(permission: Permission): Observable<DataList> {
    return this.http.get<DataList>('/api/accessible-data', {
      params: { accessLevel: permission.accessLevel }
    });
  }

  getAllData(): Observable<DataList> {
    return this.getUserInfo()
     .pipe(
        concatMap((user) => this.getPermissions(user).pipe(
          catchError((error) => {
            console.error('权限请求错误', error);
            // 这里可以返回一个默认的权限对象
            return of({ accessLevel: 'default' });
          })
        )),
        concatMap((permission) => this.getAccessibleData(permission).pipe(
          catchError((error) => {
            console.error('数据列表请求错误', error);
            // 这里可以返回一个默认的数据列表
            return of({ data: [] });
          })
        ))
      );
  }
}

在组件中使用这个服务:

import { Component } from '@angular/core';
import { UserService } from './user.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  dataList: string[] = [];

  constructor(private userService: UserService) {
    this.userService.getAllData().subscribe((data) => {
      this.dataList = data.data;
    });
  }
}

解释

  1. UserService:包含三个方法分别对应三个异步请求。getAllData 方法使用 concatMap 操作符将三个请求按顺序连接起来,并使用 catchError 处理每个请求可能出现的错误。
  2. 组件 AppComponent:注入 UserService 并调用 getAllData 方法,订阅结果并更新组件中的数据。