本文介绍了Angular SSR 刷新/加载页面挂起 Api 调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 Angular 9 .net 核心 spa 应用程序.在使用 api 调用的页面上,应用程序卡住(在 Chrome 中的网络选项卡上等待)并返回(失败)net:ERR_EMPTY_RESPONSE

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

主页运行良好,并在 ng-init 事件和其他页面上使用 api 没有 api 调用工作正常,我可以在这些页面之间来回跳转而不会出现问题.只是其他依赖 api 调用的页面会出现问题.

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.

web.config 是空的,因为我只是在 VS 2019 中构建并发布.在 localhost:4200 上一切正常,但在端口 localhost:4000 (ssr) 上出现问题

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

请参阅下面的代码 - 我在一个非常简单的 api 调用中制作的示例页面,其中数据正确传递回组件.当我尝试 url "http://localhost:4200/food-facts3/3"使用 ng serve 工作正常,但是当我尝试 "http://localhost:4000/food-facts3/3" 它卡在 Chrome 中 - 使用 ssr.url "http://localhost:4000/food-facts3/3" 等待大约 3 分钟后返回(失败)net:ERR_EMPTY_RESPONSE.iisnode npm 命令提示符显示错误-cannot read property pipe of undefined PendingInterceptorService.Intercept"

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

    }

}

应用路由

  {
    path: 'food-facts3/:id',
    component: Fact3Component,
    resolve: { fact: 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 服务

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

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

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 { }

应用模块

@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 {
}

推荐答案

如果 !isPlatformBrowser,因为 Mike 指出代码已更新并且现在工作正常,感谢 Mike

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

这篇关于Angular SSR 刷新/加载页面挂起 Api 调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 03:12