0

我正在开发一个带有 angular 8 和 ngrx 的应用程序。在我以隐身模式测试我的应用程序之前,一切都很顺利。突然,一个 url 在导航开始和导航结束之间几乎 50 秒开始工作得很慢。我观察到启用 redux-devtool 扩展似乎可以解决问题(每次都有效)。不知道这里发生了什么。需要时间的路由的解析器需要进行 3 个 api 调用,但这些调用是在我单击路由时发生的,但解析器需要 50 秒才能到达组件。这是详细信息。如果需要其他任何东西,请告诉我:

包.json

    {
  "name": "sfe",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve  --configuration=proxy --proxy-config proxy.config.json",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~8.2.14",
    "@angular/common": "~8.2.14",
    "@angular/compiler": "~8.2.14",
    "@angular/core": "~8.2.14",
    "@angular/forms": "~8.2.14",
    "@angular/platform-browser": "~8.2.14",
    "@angular/platform-browser-dynamic": "~8.2.14",
    "@angular/router": "~8.2.14",
    "@auth0/angular-jwt": "^4.0.0",
    "@ngrx/effects": "^8.6.0",
    "@ngrx/entity": "^8.6.0",
    "@ngrx/router-store": "^8.6.0",
    "@ngrx/schematics": "^8.6.0",
    "@ngrx/store": "^8.6.0",
    "@ngrx/store-devtools": "^8.6.0",
    "@ngx-translate/core": "^12.1.2",
    "@ngx-translate/http-loader": "^4.0.0",
    "core-js": "^2.5.4",
    "include-media": "^1.4.9",
    "moment": "^2.24.0",
    "moment-timezone": "^0.5.28",
    "node-sass": "~4.13.0",

    "rxjs": "~6.4.0",
    "rxjs-compat": "~6.4.0",
    "tslib": "~1.9.0",
    "webcomponents.js": "^0.7.24",
    "zone.js": "~0.9.1"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.803.25",
    "@angular-devkit/build-webpack": "^0.803.2",
    "@angular/cli": "~8.3.25",
    "@angular/compiler-cli": "~8.2.14",
    "@angular/language-service": "~8.2.14",
    "@types/node": "~8.9.4",
    "@types/jasmine": "~3.3.8",
    "@types/jasminewd2": "~2.0.3",
    "codelyzer": "^5.0.0",
    "jasmine-core": "~3.4.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~4.1.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.1",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.4.0",
    "protractor": "~5.4.0",
    "ts-node": "~7.0.0",
    "tslint": "~5.15.0",
    "typescript": "~3.5.3"
  }
}

应用程序模块

import { AppEffects } from './app.effects';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA, ErrorHandler  } from '@angular/core';
import { TranslateModule, TranslateService, TranslateLoader } from '@ngx-translate/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { StoreModule } from '@ngrx/store';
import { reducers, metaReducers } from './reducers';
import { CoreModule } from './core/core.module';
import { AuthModule } from './features/auth/auth.module';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { environment } from '../environments/environment';
import { EffectsModule, Actions } from '@ngrx/effects';
import {RouterState, StoreRouterConnectingModule } from '@ngrx/router-store';
import { HttpClient } from '@angular/common/http';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { GlobalErrorHandler } from './core/error-handling/global-exception-handling';
import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
import { HashLocationStrategy, LocationStrategy  } from '@angular/common';
import { WindowRefService } from './core/services/window-ref.service';


export  function  HttpLoaderFactory(http:  HttpClient) {
  return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [   
    BrowserModule,

    AuthModule.forRoot(),
    TranslateModule.forRoot(),    
    CoreModule.forRoot(),
    AppRoutingModule,
    StoreRouterConnectingModule.forRoot({
      stateKey: 'router',
      routerState:RouterState.Minimal
    }),

    StoreModule.forRoot(reducers, {
      metaReducers,
      runtimeChecks: {
        strictStateImmutability: true,
        strictActionImmutability: true
      }
    }),
    StoreDevtoolsModule.instrument({ maxAge: 25, logOnly: environment.production }),
    EffectsModule.forRoot([AppEffects]),
    StoreRouterConnectingModule.forRoot(),
    TranslateModule.forRoot({
      loader: {
        provide:  TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    })
  ],
  providers: [
    WindowRefService,
    {provide : LocationStrategy , useClass: HashLocationStrategy},
    {
      provide: TranslateService,
      useClass: I18nService
    },
    {
      provide: I18nService,
      useExisting: TranslateService
    },
    {
      provide: JWT_OPTIONS, useValue: JWT_OPTIONS
    },
    JwtHelperService,
    { provide: "BASE_API_URL", useValue: environment.apiUrl },
    { provide: ErrorHandler, useClass: GlobalErrorHandler }
  ],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule { }

RoutingModule.ts(延迟加载)

import { NotificationsResolver } from './resolvers/notifications.resolver';
import { NgModule } from '@angular/core';
import { Routes, RouterModule, CanActivate } from '@angular/router';
import { AuthGuard } from '../../auth/auth.guards';

const settingsroutes: Routes = [
  {
    path: '',
    component: SettingsComponent,
    children: [
      { path: 'notifications', component: SettingsComponent, data: { 'index': 1 }, resolve:{NotificationsResolver}},
    ],
    canActivate: [AuthGuard]
  }
];

@NgModule({
  imports: [RouterModule.forChild(settingsroutes)],
  exports: [RouterModule]
})
export class SettingsRoutingModule { }

解析器.ts

import { loadContactInfo, loadNotificationMobileCarriers } from './../ngrx/settings.actions';
import { areNotificationSettingsLoaded, areContactInfoLoaded, areNotificationMobileCarriersLoaded } from './../ngrx/settings.selectors';
import { getUserDetails } from '../../../auth/ngrx/auth.selectors';
import { User } from 'src/app/core/models/User';
import { tap, filter, finalize, first } from 'rxjs/operators';
import { Observable, concat, merge } from 'rxjs';
import { Store, select } from '@ngrx/store';
import { AppState } from '../../../../reducers/index';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Injectable } from '@angular/core';
import { NotificationsRequestModel } from '../models/requestmodel/notifications-request.model';
import { loadNotificationSettings } from '../ngrx/settings.actions';



@Injectable()
export class NotificationsResolver implements Resolve<any>{
    loadingNotifications = false;
    loadingContactInfo = false;
    loadingMobileCarriers = false;
    notificationsRequest :NotificationsRequestModel = new NotificationsRequestModel();
    userDetail$ : Observable<any>;
    userDetail :User;

    constructor(private store: Store<AppState>){
        this.notificationsRequest.userId = 4000;

    }

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

        const notificationSettingsData$=  
        this.store.pipe(
            select(areNotificationSettingsLoaded),
            tap(notificationSettingsLoaded => {
                if(!this.loadingNotifications &&  !notificationSettingsLoaded){
                    this.loadingNotifications = true;
                    this.store.dispatch(loadNotificationSettings({requestParameter :this.notificationsRequest}));
                }  

            }),

            filter(NotificationSettingsLoaded => NotificationSettingsLoaded),
            first(),
            finalize(()=> {
                this.loadingNotifications = false;
            })
        );
        const contactInfoData$ =this.store.pipe(
            select(areContactInfoLoaded),
             tap(areContactInfoLoaded => {
                if(!this.loadingContactInfo &&  !areContactInfoLoaded){
                    this.loadingContactInfo = true;
                    this.store.dispatch(loadContactInfo({requestParameter :this.notificationsRequest}));
                }  

            }),

            filter(ContactInfoLoaded => ContactInfoLoaded),
            first(),
            finalize(()=> {
               this.loadingContactInfo = false;
            })
        );
        const noificationMobileCarriers$ =this.store.pipe(
            select(areNotificationMobileCarriersLoaded),
             tap(areNotificationMobileCarriersLoaded => {
                if(!this.loadingMobileCarriers &&  !areNotificationMobileCarriersLoaded){
                    this.loadingMobileCarriers = true;
                    this.store.dispatch(loadNotificationMobileCarriers());
                }  

            }),

            filter(NotificationMobileCarriersLoaded=> NotificationMobileCarriersLoaded),
            first(),
            finalize(()=> {
               this.loadingMobileCarriers = false;
               console.log("third one")
            })
        );
 //This is done to enable two calls being made simultaneoulsy
        return merge(contactInfoData$, notificationSettingsData$, noificationMobileCarriers$)
    }
}

应用组件.ts

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  t1 : any;
  t0 : any;
  constructor(translate: TranslateService, private router: Router, private activatedRoute: ActivatedRoute,
    private store: Store<AppState>) {
  }
  ngOnInit(): void {


    this.router.events.subscribe(event => {
      switch (true) {
        case event instanceof NavigationStart: {
          this.t0 = performance.now();
          this.loading = true;
          break;
        }
        case event instanceof NavigationEnd:
        case event instanceof NavigationCancel:
        case event instanceof NavigationError: {
          this.t1 = performance.now();
          this.loading = false;
          console.log(this.t1-this.t0);
          break;
        }
        default: {
          break;
        }
      }
    });

    //load sub params    
    }
}
4

1 回答 1

1

我看到的问题 - 是减速器中的名称冲突,merge您也可以forkJoin用来并行执行所有请求。

this.store.dispatch(loadNotificationMobileCarriers())- 也需要requestParameter吗?

请尝试在下面编写代码,如果它不起作用 - 请检查控制台日志是否打印所有 3 done,并在下面的评论中告诉我。

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
    const notificationSettingsData$ =
        this.store.pipe(
            select(areNotificationSettingsLoaded),
            tap(flag => {
                if (!this.loadingNotifications && !flag) {
                    this.loadingNotifications = true;
                    this.store.dispatch(loadNotificationSettings({requestParameter: this.notificationsRequest}));
                }
            }),

            filter(flag => flag),
            first(),
            finalize(() => {
                this.loadingNotifications = false;
            }),
        );

    const contactInfoData$ = this.store.pipe(
        select(areContactInfoLoaded),
        tap(flag => {
            if (!this.loadingContactInfo && !flag) {
                this.loadingContactInfo = true;
                this.store.dispatch(loadContactInfo({requestParameter: this.notificationsRequest}));
            }

        }),
        filter(flag => flag),
        first(),
        finalize(() => {
            this.loadingContactInfo = false;
        }),
    );

    const noificationMobileCarriers$ = this.store.pipe(
        select(areNotificationMobileCarriersLoaded),
        tap(flag => {
            if (!this.loadingMobileCarriers && !flag) {
                this.loadingMobileCarriers = true;
                this.store.dispatch(loadNotificationMobileCarriers());
            }

        }),
        filter(flag => flag),
        first(),
        finalize(() => {
            this.loadingMobileCarriers = false;
        }),
    );

    return forkJoin({
        contactInfoData: contactInfoData$.pipe(tap(() => console.log('contactInfoData$ done'))),
        notificationSettingsData: notificationSettingsData$.pipe(tap(() => console.log('notificationSettingsData$ done'))),
        noificationMobileCarriers: noificationMobileCarriers$.pipe(tap(() => console.log('noificationMobileCarriers$ done'))),
    });
}
于 2020-05-20T16:24:54.683 回答