【发布时间】:2020-05-05 10:51:20
【问题描述】:
我正在使用 Angular 9 .net 核心 spa 应用程序。在带有 api 调用的页面上,应用程序卡住(在 Chrome 中的“网络”选项卡上挂起)并返回(失败)net:ERR_EMPTY_RESPONSE
主页工作正常,在 ng-init 事件上使用 api,其他没有 api 调用的页面工作正常,我可以在这些页面之间来回跳转而不会出现问题。只是依赖于 api 调用的其他页面会出现问题。
web.config 是空的,因为我只是在 VS 2019 中构建并发布。在 localhost:4200 上一切正常,但在端口 localhost:4000 (ssr) 上出现问题
请参阅下面的代码 - 我在一个非常简单的 api 调用中创建的示例页面,其中数据正确地传回了组件。当我尝试使用 ng serve 的 url "http://localhost:4200/food-facts3/3" 可以正常工作,但是当我尝试 "http://localhost:4000/food-facts3/3" 时,它会卡在 Chrome 中 - 使用 ssr。 url "http://localhost:4000/food-facts3/3" 等待大约 3 分钟,然后返回(失败的)net:ERR_EMPTY_RESPONSE。 iisnode npm 命令提示显示错误-“无法读取未定义的 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 休息服务
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);
}
}
Fact3组件
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 {
}
【问题讨论】:
-
如果你没有返回任何东西! isPlatformBrowser 在你的拦截器中..?
-
是的,感谢 MikeOne 更新了代码
标签: angular server-side-rendering angular-universal