尝试路由到 Angular 中的 404 页面时控制台出错
Error in console when trying to route to 404 page in Angular
当 URL 地址不正确时,我正在尝试创建指向 Angular 页面的路由。
控制台出错
在我的 IDE 中没有错误消息。
我在控制台上收到的唯一错误消息是:
ERROR TypeError: Cannot read property 'name' of undefined
at SingleAppareilComponent.ngOnInit (single-appareil.component.ts:19)
at callHook (core.js:2526)
at callHooks (core.js:2495)
at executeInitAndCheckHooks (core.js:2446)
at refreshView (core.js:9480)
at refreshEmbeddedViews (core.js:10590)
at refreshView (core.js:9489)
at refreshComponent (core.js:10636)
at refreshChildComponents (core.js:9261)
at refreshView (core.js:9515)
以下是我的文件:
SingleAppareilComponent
AppModule
- HTML 404 页面模板
- HTML
SingleAppareilComponent
的模板
AppareilService
single.appareil.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AppareilService } from 'services/appareil.service';
@Component({
selector: 'app-single-appareil',
templateUrl: './single-appareil.component.html',
styleUrls: ['./single-appareil.component.scss']
})
export class SingleAppareilComponent implements OnInit {
name: string = 'Appareil';
status: string = 'Statut';
constructor(private appareilService: AppareilService,
private route: ActivatedRoute) { }
ngOnInit(): void {
const id = this.route.snapshot.params['id'];
this.name = this.appareilService.getApparreilById(+id).name;
this.status = this.appareilService.getApparreilById(+id).status;
}
}
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AppareilComponent } from './appareil/appareil.component';
import { FormsModule } from '@angular/forms';
import { AppareilService } from 'services/appareil.service';
import { AuthComponent } from './auth/auth.component';
import { AppareilViewComponent } from './appareil-view/appareil-view.component';
import { RouterModule, Routes } from '@angular/router';
import { AuthService } from 'services/auth.service';
import { SingleAppareilComponent } from './single-appareil/single-
appareil.component';
import { FourOhFourComponent } from './four-oh-four/four-oh-four.component';
import { HashLocationStrategy, LocationStrategy } from '@angular/common';
const appRoutes: Routes = [
{ path: 'appareils', component: AppareilViewComponent },
{ path: 'appareils/:id', component: SingleAppareilComponent },
{ path: 'auth', component: AuthComponent },
{ path: '', component: AppareilViewComponent },
{ path: 'not-found', component: FourOhFourComponent },
{ path:'**', redirectTo: '/notfound' }
]
@NgModule({
declarations: [
AppComponent,
AppareilComponent,
AuthComponent,
AppareilViewComponent,
SingleAppareilComponent,
FourOhFourComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
RouterModule.forRoot(appRoutes)
],
providers: [
AppareilService,
AuthService,
{provide: LocationStrategy, useClass: HashLocationStrategy}
],
bootstrap: [AppComponent]
})
export class AppModule { }
它应该显示这个模板:
four-oh-four.component.html
<h2>Erreur 404</h2>
<p>La page que vous cherchez n'existe pas.</p>
而是显示这个
single-appareil.component.hmtl
<h2>{{ name }}</h2>
<p>Statut : {{ status }}</p>
<a routerLink="/appareils">Retourner à la liste</a>
appareil-service.ts
export class AppareilService {
appareils = [
{
id: 1,
name: 'Machine à laver',
status: 'éteint'
},
{
id:2,
name: 'Frigo',
status: 'allumé'
},
{
id:3,
name: 'Ordinateur',
status: 'éteint'
}
];
getApparreilById(id: number) {
const appareil = this.appareils.find(
(appareilObject) =>{
return appareilObject.id === id;
}
);
return appareil
}
switchOnAll() {
for (let appareil of this.appareils) {
appareil.status = 'allumé'
}
}
switchOffAll() {
for (let appareil of this.appareils) {
appareil.status = 'éteint'
}
}
switchOnOne(index: number) {
this.appareils[index].status = 'allumé';
}
switchOffOne(index: number) {
this.appareils[index].status = 'éteint';
}
它实际上提到了 ngOnInit 中这一行的确切行问题:
this.name = this.appareilService.getApparreilById(+id).name;
我怀疑你应该 return 一个 observable 而不是那里的值并订阅它,因为当 ngOnInit 被调用时你怎么知道你的数据被加载了 anw 。
为什么控制台会显示此错误?
ERROR TypeError: Cannot read property 'name' of undefined
at SingleAppareilComponent.ngOnInit (single-appareil.component.ts:19)
作为 ,您的组件中的函数 returned undefined
。然后一个赋值试图在同一个错误的 行 19 中访问这个不存在的对象上的 属性:
this.name = this.appareilService.getApparreilById(+id).name
如何调试?
- 打开浏览器的开发工具,进入调试器,在错误行设置断点
- 或在您的源代码中添加调试日志以显示更多详细信息
在你的 SingleAppareilComponent
中尝试记录从当前路由路径中提取的 id
参数以及 getApparreilById(+id)
:
的 return 值
const id = this.route.snapshot.params['id'];
console.log('Routed to SingleAppareilComponent to display appareil with id: ', id)
let appareil = this.appareilService.getApparreilById(+id);
console.log('AppareilService returned appareil: ', appareil):
this.name = appareil.name; // if appareil is undefined then you will get an error here
可能发生了什么?
为了进一步分析您的问题,我们必须查看您的 AppareilService
组件,尤其是方法 getApparreilById
.
测试您的服务
appareils = [{
id: 1,
name: 'Machine à laver',
status: 'éteint'
},
{
id: 2,
name: 'Frigo',
status: 'allumé'
},
{
id: 3,
name: 'Ordinateur',
status: 'éteint'
}
];
function getApparreilById(id) {
const appareil = this.appareils.find(
(appareilObject) => {
return appareilObject.id === id;
}
);
return appareil
}
/* Tested with vairous inputs: if not found, then undefined! */
console.log("getApparreilById(1) returns: ", getApparreilById(1));
console.log("getApparreilById(2) returns: ", getApparreilById(2));
console.log("getApparreilById(3) returns: ", getApparreilById(3));
console.log("getApparreilById(4) returns: ", getApparreilById(4));
console.log("getApparreilById('') returns: ", getApparreilById(''));
console.log("getApparreilById('1') returns: ", getApparreilById('1'));
所以 find
方法总是 returns undefined
if appareil with specified id
was not found.
而 undefined
只是一个标识符(或者你可以说一个占位符,表示“Uups,抱歉:没什么,nada,null”)。它没有可供访问的属性(如 name)。
所以错误信息是:
Cannot read property 'name' of undefined
有一个对象undefined
,但它没有任何属性,因此您不能读取或写入任何属性。
returning
的替代方法
你也可以return一个默认值对象,它是定义的,但是空 个值,例如:
getApparreilById(id: number) {
const appareil = this.appareils.find(a => a.id === id);
if (appareil === undefined) {
return {id: 0, name: '', status: ''}; // defined but empty object
}
return appareil;
}
关于后端 HTTP GET 调用的假设
假设该服务尝试从您的后端获取指定 id
的服装资源,例如:GET /appareils/:id
并期望 HTTP 状态为 200 的响应和体内的服装。
或者显然像这里(在不愉快的情况下)一样,如果在后端找不到具有指定 ID 的服装,则响应 HTTP 状态为 404。
那么主体可以是空的,这样 getApparreilById
return 就是一个 undefined
服装对象。如果没有对象,则没有 属性 name
.
以编程方式重定向到 404 页面
如果 undefined
被 returned(表示“未找到设备”),您可以(正如您可能希望的那样)重定向到另一个组件,例如你的 404 页面。
您的 404 页面的路径是在您应用的路由定义中定义的:
{ path: 'not-found', component: FourOhFourComponent },
然后您可以在组件中使用 Angular 的 Router
SingleAppareilComponent
:
import { Router } from '@angular/router'; // import the router module here
export class SingleAppareilComponent implements OnInit {
name: string = 'Appareil';
status: string = 'Statut';
// inject router in constructor as parameter
constructor(private appareilService: AppareilService,
private route: ActivatedRoute,
private _router: Router) {
}
ngOnInit(): void {
const id = this.route.snapshot.params['id'];
let appareil = this.appareilService.getApparreilById(+id);
if (typeof appareil === 'undefined') {
// use router to redirect to 404 page as defined in your routes
this._router.navigateByUrl('/not-found');
}
// else continue
this.name = appareil.name;
this.status = appareil.status;
}
}
注意:get
方法只调用一次(性能更好)。
未定义的测试也可以简化为 myVar === undefined
(在大多数情况下应该具有相同的效果)。
替代错误处理
另一种方法是 return 来自您的服务方法的 Promise。
这将使您可以为两种情况定义回调(快乐的 200,以及所有不快乐的人,如 404)。
见:
进一步阅读
- How can I check for "undefined" in JavaScript?
当 URL 地址不正确时,我正在尝试创建指向 Angular 页面的路由。
控制台出错
在我的 IDE 中没有错误消息。 我在控制台上收到的唯一错误消息是:
ERROR TypeError: Cannot read property 'name' of undefined
at SingleAppareilComponent.ngOnInit (single-appareil.component.ts:19)
at callHook (core.js:2526)
at callHooks (core.js:2495)
at executeInitAndCheckHooks (core.js:2446)
at refreshView (core.js:9480)
at refreshEmbeddedViews (core.js:10590)
at refreshView (core.js:9489)
at refreshComponent (core.js:10636)
at refreshChildComponents (core.js:9261)
at refreshView (core.js:9515)
以下是我的文件:
SingleAppareilComponent
AppModule
- HTML 404 页面模板
- HTML
SingleAppareilComponent
的模板
AppareilService
single.appareil.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AppareilService } from 'services/appareil.service';
@Component({
selector: 'app-single-appareil',
templateUrl: './single-appareil.component.html',
styleUrls: ['./single-appareil.component.scss']
})
export class SingleAppareilComponent implements OnInit {
name: string = 'Appareil';
status: string = 'Statut';
constructor(private appareilService: AppareilService,
private route: ActivatedRoute) { }
ngOnInit(): void {
const id = this.route.snapshot.params['id'];
this.name = this.appareilService.getApparreilById(+id).name;
this.status = this.appareilService.getApparreilById(+id).status;
}
}
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AppareilComponent } from './appareil/appareil.component';
import { FormsModule } from '@angular/forms';
import { AppareilService } from 'services/appareil.service';
import { AuthComponent } from './auth/auth.component';
import { AppareilViewComponent } from './appareil-view/appareil-view.component';
import { RouterModule, Routes } from '@angular/router';
import { AuthService } from 'services/auth.service';
import { SingleAppareilComponent } from './single-appareil/single-
appareil.component';
import { FourOhFourComponent } from './four-oh-four/four-oh-four.component';
import { HashLocationStrategy, LocationStrategy } from '@angular/common';
const appRoutes: Routes = [
{ path: 'appareils', component: AppareilViewComponent },
{ path: 'appareils/:id', component: SingleAppareilComponent },
{ path: 'auth', component: AuthComponent },
{ path: '', component: AppareilViewComponent },
{ path: 'not-found', component: FourOhFourComponent },
{ path:'**', redirectTo: '/notfound' }
]
@NgModule({
declarations: [
AppComponent,
AppareilComponent,
AuthComponent,
AppareilViewComponent,
SingleAppareilComponent,
FourOhFourComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
RouterModule.forRoot(appRoutes)
],
providers: [
AppareilService,
AuthService,
{provide: LocationStrategy, useClass: HashLocationStrategy}
],
bootstrap: [AppComponent]
})
export class AppModule { }
它应该显示这个模板:
four-oh-four.component.html
<h2>Erreur 404</h2>
<p>La page que vous cherchez n'existe pas.</p>
而是显示这个
single-appareil.component.hmtl
<h2>{{ name }}</h2>
<p>Statut : {{ status }}</p>
<a routerLink="/appareils">Retourner à la liste</a>
appareil-service.ts
export class AppareilService {
appareils = [
{
id: 1,
name: 'Machine à laver',
status: 'éteint'
},
{
id:2,
name: 'Frigo',
status: 'allumé'
},
{
id:3,
name: 'Ordinateur',
status: 'éteint'
}
];
getApparreilById(id: number) {
const appareil = this.appareils.find(
(appareilObject) =>{
return appareilObject.id === id;
}
);
return appareil
}
switchOnAll() {
for (let appareil of this.appareils) {
appareil.status = 'allumé'
}
}
switchOffAll() {
for (let appareil of this.appareils) {
appareil.status = 'éteint'
}
}
switchOnOne(index: number) {
this.appareils[index].status = 'allumé';
}
switchOffOne(index: number) {
this.appareils[index].status = 'éteint';
}
它实际上提到了 ngOnInit 中这一行的确切行问题:
this.name = this.appareilService.getApparreilById(+id).name;
我怀疑你应该 return 一个 observable 而不是那里的值并订阅它,因为当 ngOnInit 被调用时你怎么知道你的数据被加载了 anw 。
为什么控制台会显示此错误?
ERROR TypeError: Cannot read property 'name' of undefined at SingleAppareilComponent.ngOnInit (single-appareil.component.ts:19)
作为 undefined
。然后一个赋值试图在同一个错误的 行 19 中访问这个不存在的对象上的 属性:
this.name = this.appareilService.getApparreilById(+id).name
如何调试?
- 打开浏览器的开发工具,进入调试器,在错误行设置断点
- 或在您的源代码中添加调试日志以显示更多详细信息
在你的 SingleAppareilComponent
中尝试记录从当前路由路径中提取的 id
参数以及 getApparreilById(+id)
:
const id = this.route.snapshot.params['id'];
console.log('Routed to SingleAppareilComponent to display appareil with id: ', id)
let appareil = this.appareilService.getApparreilById(+id);
console.log('AppareilService returned appareil: ', appareil):
this.name = appareil.name; // if appareil is undefined then you will get an error here
可能发生了什么?
为了进一步分析您的问题,我们必须查看您的 AppareilService
组件,尤其是方法 getApparreilById
.
测试您的服务
appareils = [{
id: 1,
name: 'Machine à laver',
status: 'éteint'
},
{
id: 2,
name: 'Frigo',
status: 'allumé'
},
{
id: 3,
name: 'Ordinateur',
status: 'éteint'
}
];
function getApparreilById(id) {
const appareil = this.appareils.find(
(appareilObject) => {
return appareilObject.id === id;
}
);
return appareil
}
/* Tested with vairous inputs: if not found, then undefined! */
console.log("getApparreilById(1) returns: ", getApparreilById(1));
console.log("getApparreilById(2) returns: ", getApparreilById(2));
console.log("getApparreilById(3) returns: ", getApparreilById(3));
console.log("getApparreilById(4) returns: ", getApparreilById(4));
console.log("getApparreilById('') returns: ", getApparreilById(''));
console.log("getApparreilById('1') returns: ", getApparreilById('1'));
所以 find
方法总是 returns undefined
if appareil with specified id
was not found.
而 undefined
只是一个标识符(或者你可以说一个占位符,表示“Uups,抱歉:没什么,nada,null”)。它没有可供访问的属性(如 name)。
所以错误信息是:
Cannot read property 'name' of undefined
有一个对象undefined
,但它没有任何属性,因此您不能读取或写入任何属性。
returning
的替代方法你也可以return一个默认值对象,它是定义的,但是空 个值,例如:
getApparreilById(id: number) {
const appareil = this.appareils.find(a => a.id === id);
if (appareil === undefined) {
return {id: 0, name: '', status: ''}; // defined but empty object
}
return appareil;
}
关于后端 HTTP GET 调用的假设
假设该服务尝试从您的后端获取指定 id
的服装资源,例如:GET /appareils/:id
并期望 HTTP 状态为 200 的响应和体内的服装。
或者显然像这里(在不愉快的情况下)一样,如果在后端找不到具有指定 ID 的服装,则响应 HTTP 状态为 404。
那么主体可以是空的,这样 getApparreilById
return 就是一个 undefined
服装对象。如果没有对象,则没有 属性 name
.
以编程方式重定向到 404 页面
如果 undefined
被 returned(表示“未找到设备”),您可以(正如您可能希望的那样)重定向到另一个组件,例如你的 404 页面。
您的 404 页面的路径是在您应用的路由定义中定义的:
{ path: 'not-found', component: FourOhFourComponent },
然后您可以在组件中使用 Angular 的 Router
SingleAppareilComponent
:
import { Router } from '@angular/router'; // import the router module here
export class SingleAppareilComponent implements OnInit {
name: string = 'Appareil';
status: string = 'Statut';
// inject router in constructor as parameter
constructor(private appareilService: AppareilService,
private route: ActivatedRoute,
private _router: Router) {
}
ngOnInit(): void {
const id = this.route.snapshot.params['id'];
let appareil = this.appareilService.getApparreilById(+id);
if (typeof appareil === 'undefined') {
// use router to redirect to 404 page as defined in your routes
this._router.navigateByUrl('/not-found');
}
// else continue
this.name = appareil.name;
this.status = appareil.status;
}
}
注意:get
方法只调用一次(性能更好)。
未定义的测试也可以简化为 myVar === undefined
(在大多数情况下应该具有相同的效果)。
替代错误处理
另一种方法是 return 来自您的服务方法的 Promise。 这将使您可以为两种情况定义回调(快乐的 200,以及所有不快乐的人,如 404)。
见:
进一步阅读
- How can I check for "undefined" in JavaScript?