0

我有一个UserProfileResolverUserProfileComponent. 我注意到我可以多次单击导航链接发送大量 HTTP 请求。

是否有一种标准方法可以防止在初始请求完成之前发出后续请求?

在此处输入图像描述

导航

<li class="nav-item">
  <a [routerLink]="['/user-profile/'+userId]" class="nav-link" routerLinkActive="active">
    <i class="fa fa-user" aria-hidden="true"></i>
    <ng-container i18n>Edit Profile</ng-container>
  </a>
</li>

路由模块

const routes: Routes = [
  {
    path: ':id',
    component: UserProfileComponent,
    resolve: {data: UserProfileResolver},
  },
];

解析器

export class UserProfileResolver {

  constructor(private readonly userService: UserService, private readonly facilityService: FacilityService) {
  }

  public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {

    return new Observable((observer) => {

      forkJoin([
        this.userService.getSingle(route.paramMap.get('id')),
        this.facilityService.getAll(),
      ]).pipe(
        map(([user, facilities]) => {
          return {user, facilities};
        }),

        catchError(() => of(undefined)),

        // dont resolve on error
        tap(data => {
          if (data !== undefined) {
            observer.next(data);
          } else {
            observer.unsubscribe();
          }
          observer.complete();
        }),
      ).subscribe();
    });
  }
}

4

2 回答 2

0

所以我最终只是禁用了按钮,直到导航解决

导航

<li class="nav-item">
  <a (click)="userProfileClick()" [class.disabled]="userProfileNavigating"
     [routerLink]="['/user-profile/'+userId]" class="nav-link" routerLinkActive="active">
    <i aria-hidden="true" class="fa fa-user"></i>
    <ng-container i18n>Edit Profile</ng-container>
  </a>
</li>

侧面导航

export class SideNavComponent {

  public userId: string;

  public userProfileNavigating: boolean;

  constructor(public readonly authService: AuthService,
              private readonly router: Router,
  ) {
    this.userId = authService.userId;

    // noticed i could click a router link a bunch of times before it resolved
    router.events.pipe(filter(e => e instanceof NavigationEnd || e instanceof NavigationCancel)).subscribe(e => {
      this.userProfileNavigating = false;
    });
  }

  userProfileClick() {
    if (this.router.routerState.snapshot.url !== `/user-profile/${this.userId}`) {
      this.userProfileNavigating = true;
    }
  }
}

解析器

为 Angular 10 更新,这通过使用取消解析器导航EMPTY

export class UserProfileResolver implements Resolve<any> {

  constructor(private readonly userService: UserService, private readonly facilityService: FacilityService) {
  }

  public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
    Observable<{ user: User; facilities: Array<Facility> }> {
    return forkJoin([
      this.userService.getSingle(route.paramMap.get('id')),
      this.facilityService.getAll(),
    ]).pipe(
      map(([user, facilities]) => {
        return {user, facilities};
      }),
      catchError(() => EMPTY),
    );
  }
}
于 2020-09-24T23:18:31.287 回答
0

您可以为 Angular 使用一些Block UI实现,例如ng-block-ui,它可以配置为在 httpRequests 上自动启动,并在响应解析之前阻止用户进行任何其他交互;

您可以通过以下命令安装它:

npm install ng-block-ui --save

并按如下方式导入您的 Angular 应用程序:

// All other imports
import { BlockUIModule } from 'ng-block-ui';
 
@NgModule({
  imports: [
    BlockUIModule.forRoot()
  ],
  ...
})
export class AppModule { }

这是Stackblitz上的一个简单示例。

于 2020-09-24T19:15:17.693 回答