尝试路由到 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)

以下是我的文件:

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?