首页 > 解决方案 > Angular8:如果没有返回数据,则路由到 404,BEFORE 组件显示

问题描述

使用 Angular8,我将通过 url 的 params-id 显示用户的个人资料:

http://localhost:4200/user/El231A

如果无法检索到任何用户,我将路由到我的 404 错误页面。

现在下面的代码工作得很好。但是,到 404 错误页面的路由不会立即发生:最终用户会在一秒钟内看到我的空组件。但是,如果无法检索到用户配置文件,我想在我的组件显示任何内容之前路由到 404。

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.scss']
})
export class UserComponent implements OnInit {
  userprofile: Userprofile;


  constructor(private httpHandler: HttpHandlerService,
              private authService: AuthService,
              private route: ActivatedRoute) {
  }

  ngOnInit(): void {
    this.route.params.subscribe(params => {
      this.getUserprofile(params[`id`]);
    });
  }

  getUserprofile(userId: string): void {
    this.httpHandler.getUserProfile(userId)
      .subscribe(userprofile => this.userprofile = userprofile);
  }

}

(小旁注:我有意订阅 id 参数,因为如果 ID 即时更改,我想更新我的 GUI,请参阅此处了解更多详细信息:Angular 2 reload route on param change

如果我无法成功获取具有 id 的用户,我的 http 处理程序将路由到我的 404 错误页面:

export class HttpHandlerService {
  userApiUrl: string;

  constructor(private http: HttpClient, private router: Router) { }

  getUserProfile(userId: string): Observable<Userprofile> {
    const url = `${this.userApiUrl}/${userId}`;
    return this.http.get<Userprofile>(url).pipe(
      tap(_ => console.log(`fetched userprofile with id=${userId}`)),
      catchError(this.handleError<Userprofile>(`getUserProfile id=${userId}`))
    );
  }

  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
      console.log(`${operation} failed: ${error.message}`);
      this.router.navigate(['404']).then();
      return of(result as T);
    };
  }

我不觉得将 ngOnInit() 代码部分移动到构造函数中是正确的方法。而且我不知道 ngOnInit() 之前的角度生命周期事件会适合。

有什么想法吗?提前致谢。

标签: angularangular2-routingangular8angular2-services

解决方案


你可以在这里做一点改变:

import { from, of, Observable } from 'rxjs';
import { switchMap, delay } from 'rxjs/operators';

private handleError<T>(operation = 'operation', result?: T) {
  return (error: any): Observable<T> => {
    console.log(`${operation} failed: ${error.message}`);

    // switchMap will be called only after navigate resolves
    return from(this.router.navigate(['404'])).pipe(
      delay(1000),
      switchMap((_: boolean) => of<T>(result))
    );
  };
}

推荐阅读