Angular中从route.params.subscribe获取userId时出现未定义属性错误
问题:Angular接收URL参数时抛出TypeError,但功能正常
开发用户激活页面,通过URL获取userId后请求后端激活用户,后端能正常接收请求并处理,但Angular控制台抛出以下错误:
reset-password.component.ts:35 ERROR TypeError: Cannot set properties of undefined (setting 'userId') at Object.next (reset-password.component.ts:37:29) at ConsumerObserver.next (Subscriber.js:91:33) at SafeSubscriber._next (Subscriber.js:60:26) at SafeSubscriber.next (Subscriber.js:31:18) at BehaviorSubject._subscribe (BehaviorSubject.js:12:44) at BehaviorSubject._trySubscribe (Observable.js:37:25) at BehaviorSubject._trySubscribe (Subject.js:74:22) at Observable.js:31:30 at errorContext (errorContext.js:19:9) at BehaviorSubject.subscribe (Observable.js:22:21)
组件代码
import { Component, OnInit } from '@angular/core'; import { ResetPasswordService } from './reset-password.service'; import { CommonModule } from '@angular/common'; import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { MatFormFieldModule } from '@angular/material/form-field'; @Component({ selector: 'app-reset-password', templateUrl: './reset-password.component.html', styleUrls: ['./reset-password.component.css'], standalone: true, imports: [ MatFormFieldModule, MatDialogModule, ReactiveFormsModule, CommonModule, FormsModule, ] }) export class ResetPasswordComponent { resetData = new FormGroup({ email: new FormControl('', [Validators.required, Validators.email]), password: new FormControl('', Validators.required), confirmPassword: new FormControl('', [Validators.required]), }); resetDto!: { email: string, password: string, resetCode: string | null, userId: string | null }; isVerified = false; constructor(public resetPasswordService: ResetPasswordService, private route: ActivatedRoute, public router: Router) { this.route.params.subscribe((params: { userId?: string }) => { if (params && params.userId != null) { this.resetDto.userId = params.userId; // 报错行 this.resetPasswordService.verifyUser(params.userId).then(response => { this.isVerified = response; }); } }); } }
服务代码
import { Injectable } from '@angular/core'; import { AppService } from '../app.service'; import { firstValueFrom } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class ResetPasswordService { constructor(public appService: AppService) { } resetPassword(resetDto: { email: string, password: string }): Promise<boolean> { let result = firstValueFrom(this.appService.PUT<boolean>(`users/reset-password`, resetDto )).then(resetResult => { return resetResult; }, error => { return error.status; }); return result; } verifyUser(userId: string): Promise<boolean> { let result = firstValueFrom(this.appService.GET<boolean>(`users/verify?userId=${userId}` )).then(resetResult => { return resetResult; }, error => { return error.status; }); return result; } }
HTML模板
<p>reset-password works!</p> <div *ngIf="resetDto.userId"> <p>you're already verified! Go to the webpage and log in to start using our site!</p> </div>
原因分析
错误根源在于resetDto仅做了类型声明(使用!非空断言),但未实际初始化对象,导致this.resetDto为undefined。当执行this.resetDto.userId = params.userId时,自然会抛出“无法给undefined设置属性”的错误。
虽然后端能正常接收请求,是因为服务调用时直接使用了params.userId,而非this.resetDto.userId,所以功能不受影响,但错误本身会影响应用稳定性。
解决方案
初始化resetDto对象,替换原来的类型声明:
// 替换原resetDto声明 resetDto: { email: string, password: string, resetCode: string | null, userId: string | null } = { email: '', password: '', resetCode: null, userId: null };
或者在构造函数中先初始化对象:
constructor(public resetPasswordService: ResetPasswordService, private route: ActivatedRoute, public router: Router) { // 先初始化resetDto this.resetDto = { email: '', password: '', resetCode: null, userId: null }; this.route.params.subscribe((params: { userId?: string }) => { if (params && params.userId != null) { this.resetDto.userId = params.userId; this.resetPasswordService.verifyUser(params.userId).then(response => { this.isVerified = response; }); } }); }
这样既可以修复错误,也能保证HTML模板中*ngIf="resetDto.userId"的判断不会因为resetDto未定义而抛出额外错误。
内容的提问来源于stack exchange,提问作者Alfredo Marin
相关产品推荐
相关产品推荐

