Angular8: маршрут до 404, если данные не возвращены, ДО компонента показывает - PullRequest
0 голосов
/ 08 апреля 2020

Используя Angular8, я показываю профиль пользователя по параметру URL-адреса URL:

http://localhost:4200/user/El231A

Если ни одного пользователя не удается найти, я бы перенаправил на свою страницу ошибки 404 .

Теперь приведенный ниже код работает просто отлично. Однако перенаправление на страницу ошибки 404 происходит не сразу: конечный пользователь увидит мой пустой компонент за долю секунды. Тем не менее, я хотел бы направить на 404, ДО того, как мой компонент покажет что-нибудь, если userprofile не может быть получен.

@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);
  }

}

(small sidenote: я намеренно подписываюсь на параметр id, так как я хочу обновить свой GUI если идентификатор меняется на лету, см. Здесь для получения дополнительной информации: Angular 2 маршрут перезагрузки при изменении параметра )

Мой обработчик 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 () в конструктор было бы правильным подходом. И я не знаю о событии жизненного цикла angular перед ngOnInit (), которое бы подходило.

Есть мысли? Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 08 апреля 2020

Вы можете сделать небольшое изменение здесь:

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))
    );
  };
}
1 голос
/ 08 апреля 2020

как насчет использования resolver.

данные могут быть получены при навигации angular маршрутизатора.

это ссылка о разрешении

https://angular.io/api/router/Resolve

Сначала

@Injectable()
export class exampleResolver implements Resolve<any> {
    constructor(private exampleService: ExampleService) { }

    resolve(route: ActivatedRouteSnapshot) {
        console.log('resolver', route);
        return this.exampleService.getList()
    }
}

Затем пример модуля


    {
                path: "list", component: ExampleListComponent,
                data: { title: 'title.list' },
                resolve: { users: exampleListResolver }
            },

Надеюсь, это поможет

...