代码之家  ›  专栏  ›  技术社区  ›  coder

TypeError:无法读取Angular RxJS订阅中未定义的属性(读取“filter”)

  •  0
  • coder  · 技术社区  · 2 年前

    我在我的Angular组件中遇到了一个具有RxJS可观察性的TypeError。错误消息“TypeError:无法读取未定义的属性(读取'filter')”指向我在数组上使用的筛选器。

    当尝试筛选this.users时,该错误特别发生在userService.users$订阅中。其目的是将已登录的用户从列表中排除。

    我应该采取什么不同的做法?

    以下是相关代码的简化版本:

    用户列表组件.ts

    export class UserListComponent implements OnInit, OnDestroy {
      protected readonly Object = Object;
      users!: User[];
      usersSubscription!: Subscription;
      loggedUser!: User;
      loggedUserSubscription!: Subscription;
      groupedAndSortedUsers!: { [key: string]: User[] };
    
      constructor(public userService:UserService) {
      }
    
      ngOnInit() {
    
        this.loggedUserSubscription = this.userService.loggedUser$.subscribe(user => {
          this.loggedUser = user;
        })
    
        this.userService.users$.subscribe(users => {
            this.users = users.filter(user => user?.id !== this.loggedUser.id);
            // Remove the current logged-in user
            const filteredUsers = this.users.filter(user => user?.id !== this.loggedUser.id);
            this.groupedAndSortedUsers = this.userService.groupAndSortUsers(filteredUsers);
        });
      }
    
      ngOnDestroy() {
        this.usersSubscription.unsubscribe();
        this.loggedUserSubscription.unsubscribe();
      }
    }
    

    user.service.ts

    export class UserService {
      private _users$: BehaviorSubject<User[] | undefined> = new BehaviorSubject<User[] | undefined>(undefined);
      private _loggedUser$: BehaviorSubject<User | undefined> = new BehaviorSubject<User | undefined>(undefined);
    
      constructor(private userHttpService: UserHttpService, private router: Router, private dtoMapperService: DtoMapperService, private matSnackBar: MatSnackBar,) {
        this.fetchUsers();
        this.fetchLoggedUser();
      }
    
      public get users$(): Observable<User[]> {
        return this._users$.asObservable() as Observable<User[]>;
      }
    
      public get users(): User[] {
        return this._users$.getValue() as User[];
      }
    
      public get loggedUser$(): Observable<User> {
        return this._loggedUser$.asObservable() as Observable<User>;
      }
    
      public get loggedUser(): User {
        return this._loggedUser$.getValue() as User;
      }
    
      public set users(users: User[]) {
        this._users$.next(users);
      }
    
      public set loggedUser(user: User) {
        this._loggedUser$.next(user);
      }
    
      public fetchUsers() {
        this.userHttpService.fetchUsers().subscribe({
          next: (usersDtos: UserDto[]) => {
            const users = usersDtos.map(userDto => this.dtoMapperService.mapUserDtoToUser(userDto));
            this._users$.next(users);
          }
        });
      }
    
      public fetchLoggedUser() {
        this.userHttpService.fetchLoggedUser().subscribe({
          next: (userDto: UserDto) => {
            this._loggedUser$.next(this.dtoMapperService.mapUserDtoToUser(userDto))
          }
        })
      }
    
      public groupAndSortUsers(users: User[]): { [key: string]: User[] } {
        const sortedUsers: { [key: string]: User[] } = {};
    
        users.forEach(user => {
          const firstLetter = user.name.charAt(0).toUpperCase();
          if (!sortedUsers[firstLetter]) {
            sortedUsers[firstLetter] = [];
          }
          sortedUsers[firstLetter].push(user);
        });
    
        const sortedKeys = Object.keys(sortedUsers).sort();
    
        sortedKeys.forEach(letter => {
          sortedUsers[letter].sort((a, b) => a.name.localeCompare(b.name));
        });
    
        const sortedUsersResult: { [key: string]: User[] } = {};
        sortedKeys.forEach(letter => {
          sortedUsersResult[letter] = sortedUsers[letter];
        });
    
        return sortedUsersResult;
      }
    }
    

    用户列表组件.ts

    <div class="user-list-box">
        <mat-list-item role="listitem">ME</mat-list-item>
        <mat-divider></mat-divider>
        <app-user [user]="userService.loggedUser"></app-user>
        
        <mat-list role="list">
          @for (letter of Object.keys(groupedAndSortedUsers); track letter) {
            <mat-list-item role="listitem">{{ letter }}</mat-list-item>
            <mat-divider></mat-divider>
            @for (user of groupedAndSortedUsers[letter]; track user.id) {
              <app-user [user]="user"></app-user>
            }
         }
        </mat-list>
    </div>
    
    1 回复  |  直到 2 年前
        1
  •  1
  •   Eliseo    2 年前

    您需要检查用户是否是订阅函数中的数组

    例如,您可以使用 (users || []) ,因此,如果用户是“未定义的”,则获取空数组的值。

    this.userService.users$.subscribe((users:any[]) => {
       //you can check the value of users
       console.log(users)
       this.users = (users || []).filter(user => user?.id !== this.loggedUser.id);
       ...
    })