如何解决XMLHttpRequest.send(... dist \ fxcore \ server \ main.js:200768:19)上的错误NetworkError

时间:2020-04-27 00:57:42

标签: javascript node.js angular xmlhttprequest angular9

我是Angular的新手。我刚刚完成了我的角度Web应用程序的开发。当我在生产过程中使用ng serve服务我的应用程序时,一切正常。我添加了通用角度。现在,当我运行npm run dev:ssr或npm run build:ssr && npm run serve:ssr时,我的应用程序将拒绝打开,并在控制台中抛出NetworkError响应。我注意到通过类'constructors(){..}'发送http请求的次数发生了此错误。我已经浏览了几种解决方案,但无法了解我做错了什么。我的后端是使用nodejs和express开发的。我将不胜感激。 这是我总是在控制台中得到的错误响应的完整示例。

ERROR NetworkError
    at XMLHttpRequest.send (C:\Users\MRBEN\Desktop\Angular\fxcore\dist\fxcore\server\main.js:200768:19)
    at Observable._subscribe (C:\Users\MRBEN\Desktop\Angular\fxcore\dist\fxcore\server\main.js:19025:17)
    at Observable._trySubscribe (C:\Users\MRBEN\Desktop\Angular\fxcore\dist\fxcore\server\main.js:186304:25)
    at Observable.subscribe (C:\Users\MRBEN\Desktop\Angular\fxcore\dist\fxcore\server\main.js:186290:22)
    at scheduleTask (C:\Users\MRBEN\Desktop\Angular\fxcore\dist\fxcore\server\main.js:105897:32)
    at Observable._subscribe (C:\Users\MRBEN\Desktop\Angular\fxcore\dist\fxcore\server\main.js:105959:13)
    at Observable._trySubscribe (C:\Users\MRBEN\Desktop\Angular\fxcore\dist\fxcore\server\main.js:186304:25)
    at Observable.subscribe (C:\Users\MRBEN\Desktop\Angular\fxcore\dist\fxcore\server\main.js:186290:22)
    at subscribeToResult (C:\Users\MRBEN\Desktop\Angular\fxcore\dist\fxcore\server\main.js:196385:23)
    at MergeMapSubscriber._innerSub (C:\Users\MRBEN\Desktop\Angular\fxcore\dist\fxcore\server\main.js:191575:116)```

3 个答案:

答案 0 :(得分:2)

我遇到了同样的错误。尝试从TransferHttpCacheModule中删除app.module,并创建自己的自定义http传输拦截器文件。

我制作了一个名为transfer-state.interceptor.ts的文件,然后将其添加到app.module providers:[]中进行处理。下面的示例将显示我如何进行连接。我不确定这是否一定对您有用,但这确实使该错误对我消失了。


//app.module.ts

import { BrowserModule, BrowserTransferStateModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from "@angular/common/http";
//import {TransferHttpCacheModule } from '@nguniversal/common';

import { AppRoutingModule } from './app-routing/app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './modules/home/home.component';
import { SliderComponent } from './components/slider/slider.component';
import { WindowRefService } from './services/window-ref.service';
//import { TransferHttpInterceptorService } from './services/transfer-http-interceptor.service';
import { TransferStateInterceptor } from './interceptors/transfer-state.interceptor';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    SliderComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'serverApp' }),
    BrowserTransferStateModule,
    AppRoutingModule,
    HttpClientModule,
    ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })
  ],
  providers: [
    WindowRefService,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: TransferStateInterceptor,
      multi: true
    }
],
  bootstrap: [AppComponent]
})
export class AppModule { }

这是自定义传输状态文件的一种版本,但是如果此方法不起作用,则有几种方法可以实现。


//transfer-state.interceptor.ts

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { Observable, of } from 'rxjs';
import { StateKey, TransferState, makeStateKey } from '@angular/platform-browser';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
import { tap } from 'rxjs/operators';

@Injectable()
export class TransferStateInterceptor implements HttpInterceptor {

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

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

    // For this demo application, we will only worry about State Transfer for get requests.
    if (request.method !== 'GET') {
      return next.handle(request);
    }


    // Use the request url as the key.
    const stateKey: StateKey<string> = makeStateKey<string>(request.url);

    // For any http requests made on the server, store the response in State Transfer.
    if (isPlatformServer(this.platformId)) {
      return next.handle(request).pipe(
        tap((event: HttpResponse<any>) => {
          this.transferState.set(stateKey, event.body);
        })
      );
    }

    // For any http requests made in the browser, first check State Transfer for a 
    // response corresponding to the request url.
    if (isPlatformBrowser(this.platformId)) {
      const transferStateResponse = this.transferState.get<any>(stateKey, null);
      if (transferStateResponse) {
        const response = new HttpResponse({ body: transferStateResponse, status: 200 });

        // Remove the response from state transfer, so any future requests to 
        // the same url go to the network (this avoids us creating an 
        // implicit/unintentional caching mechanism).
        this.transferState.remove(stateKey);
        return of(response);
      } else {
        return next.handle(request);
      }
    }
  }
}

如果您想为此添加自定义缓存,可以通过安装memory-cache来实现,但是我还没有尝试过。有关更多参考,这些文章对我有很大帮助,也许它们也可以为您提供帮助。

https://itnext.io/angular-universal-caching-transferstate-96eaaa386198

https://willtaylor.blog/angular-universal-for-angular-developers/

https://bcodes.io/blog/post/angular-universal-relative-to-absolute-http-interceptor

如果没有,可能需要将ServerTransferStateModule添加到您的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';

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

祝你好运!

答案 1 :(得分:1)

我仍然收到此ERROR NetworkError,但我找到了另一种方法来使此错误消失。我认为这个答案很重要,因为我得到了上面发布的相同错误。如果这可以帮助遇到同一服务器错误的任何人,那就太好了。

如果在重新加载OnInit示例时首先向服务器isPlatformBrowser发送了api请求,请首先检查ng-universal

import { Component, OnInit, PLATFORM_ID, Inject } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { HttpClient, HttpHeaders } from '@angular/common/http';

public testBrowser: boolean;
export class HomeComponent implements OnInit {

  public testBrowser  : boolean;
  public data         : any;
  
  constructor(private http: HttpClient, @Inject(PLATFORM_ID) platformId: string) {
    this.testBrowser = isPlatformBrowser(platformId);
  }

  ngOnInit() {
    if (this.testBrowser) {
      //avoid server NETWORK error
      this.data = this.http.get('/api');
    }
  }
}

在尝试先检查isPlatformBrowser === true OnInit之前,尝试从客户端进行服务器调用时遇到了同样的错误,这解决了我的问题。希望这可以解决这个错误。

作为参考,此答案帮助我解决了这个长期存在的错误。 https://stackoverflow.com/a/46893433/4684183

答案 2 :(得分:0)

我遇到了同样的错误,通过在 URL 中添加 localhost 解决了。

之前:

this.http.get<IData[]>('/api/data')

之后

this.http.get<IData[]>('http://localhost:4200/api/data')