Angular SSR Refresh/Load Page Pending Api Call

淺唱寂寞╮ 提交于 2021-01-29 04:59:13

问题


I am using an Angular 9 .net core spa app. On pages with api call the app becomes stuck (pending on the Network tab in Chrome) and comes back with (failed) net:ERR_EMPTY_RESPONSE

The home page works fine and uses an api on the ng-init event and other pages without an api call work fine and I can jump between these pages back and forth without an issue. It just other pages that that depend on an api call give the problem.

The web.config is empty as I just build within VS 2019 and publish. Everything works fine on localhost:4200 but on port localhost:4000 (ssr) is when the issue occurs

See code below - a sample page I made on a very simple api call with data correctly passed back to the component. When I try the url "http://localhost:4200/food-facts3/3" works fine using ng serve but when I try "http://localhost:4000/food-facts3/3" it gets stuck in Chrome - using ssr. The url "http://localhost:4000/food-facts3/3" stays pending for about 3 minutes and comes back with (failed) net:ERR_EMPTY_RESPONSE. The iisnode npm command prompt shows the error - "cannot read property pipe of undefined PendingInterceptorService.Intercept"

@Injectable()
 export class HttpConfigInterceptor implements HttpInterceptor, OnInit {
constructor(@Inject(PLATFORM_ID) private platformId: any, public errorDialogService: ErrorDialogService) { }

ngOnInit() {
}

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

   if (isPlatformBrowser(this.platformId)) {
        const token = localStorage.getItem('Token');

        if (token) {
            request = request.clone({ headers: request.headers.set('Authorization', 'Bearer ' + token) });
        }
    }
        request = request.clone({ headers: request.headers.set('Accept', 'application/json') });

        return next.handle(request); //This is to do more but just trying to isolate the bug

    }

}

app-routing

  {
    path: 'food-facts3/:id',
    component: Fact3Component,
    resolve: { fact: FactResolver }
  }

FactResolver

export class FactResolver implements Resolve<Fact> {

constructor(private srv: FactApiRestService, @Inject(PLATFORM_ID) private platformId, private transferState: TransferState) { }

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

    const factId = route.params['id'].toString();

    const Key = makeStateKey<Fact>('fact-' + factId);

    if (this.transferState.hasKey(Key)) {

        const data = this.transferState.get<Fact>(Key, null);

        this.transferState.remove(Key);

        return of(data);
    }
    else {
        return this.srv.getFact(factId)
            .pipe(
                first(),
                tap(data => {
                    if (isPlatformServer(this.platformId)) {
                        this.transferState.set(Key, data);
                    }
                })
            );
    }
}

}

Fact Api Rest Service

const apiUrl = environment.apiRestUrl + '/fact';

@Injectable({
providedIn: 'root'
})
export class FactApiRestService {
fact: Fact;
factList: Fact[];

constructor(private http: HttpClient) {
}

getFact(factId: number){
  return this.http.get<Fact>(apiUrl + '/factbyId/' + factId);
}

}

Fact3Component

export class Fact3Component implements OnInit {
fact: Fact;
constructor(private route: ActivatedRoute, private srv: FactApiRestService, private title: Title, 
private meta: Meta) { }

ngOnInit() {
  this.fact = this.route.snapshot.data['fact'];
  this.title.setTitle(this.fact.Name);
  this.meta.addTag({ name: 'description', content: this.fact.FactTypeName });
}

}

Web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
  <system.webServer>
  <handlers>
    <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" 
  />
  </handlers>
  <aspNetCore processPath=".\MyApp.WebUI.exe" stdoutLogEnabled="false" stdoutLogFile=".\stdout" 
   hostingModel="inprocess" />
  </system.webServer>
 </location>
</configuration>

app.server.module

import { NgModule } from '@angular/core';
import { ServerModule, ServerTransferStateModule } from '@angular/platform-server';

import { AppModule } from './app.module';
import { AppComponent } from './app.component';
import { FlexLayoutServerModule } from '@angular/flex-layout/server';

@NgModule({
  imports: [
    AppModule,
    ServerModule,
    FlexLayoutServerModule,
    ServerTransferStateModule
  ],
  bootstrap: [AppComponent],
})
export class AppServerModule { }

app.module

@NgModule({
  imports: [
    MatIconModule,
    MatCardModule,
    MatButtonModule,
    MatProgressBarModule,
    MatTooltipModule,
    MatRadioModule,
    MatExpansionModule,
    ToastrModule.forRoot({ positionClass: 'toast-top-center' }),
    FlexLayoutModule,
    MaterialModule,
    FormsModule,
    FurySharedModule,
    AllthemealModule,
    // Angular Core Module // Don't remove!
    BrowserModule.withServerTransition({ appId: 'serverApp' }),
    BrowserTransferStateModule,
    BrowserAnimationsModule,
    HttpClientModule,
    HttpClientJsonpModule,
    CommonModule,
    // Fury Core Modules
    AppRoutingModule,

    // Layout Module (Sidenav, Toolbar, Quickpanel, Content)
    LayoutModule,

    // Displays Loading Bar when a Route Request or HTTP Request is pending
    PendingInterceptorModule,

    // Register a Service Worker (optional)
    // ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
  providers: [
    FactApiRestService,
    FactResolver,
    { provide: HTTP_INTERCEPTORS, useClass: HttpConfigInterceptor, multi: true },
  ]
})
export class AppModule {
}

回答1:


I forgot return if ! isPlatformBrowser as Mike pointed out code updated and working fine now thanks Mike



来源:https://stackoverflow.com/questions/61611378/angular-ssr-refresh-load-page-pending-api-call

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!