Angular Узловой сервер возвращает Вы указали «неопределенное», где ожидался поток - PullRequest
1 голос
/ 07 апреля 2020

Я использую angular 9 + универсальный. Нет ошибок, пока я запускаю ng serve, затем я создаю приложение с npm run build:ssr и пытаюсь запустить с узлом: узел dist / app / server / main. js и получаю следующую ошибку в терминале:

Узел Express сервер прослушивает http://localhost: 4000 Ошибка типа: Вы указали «неопределенное» там, где ожидался поток. Вы можете предоставить Observable, Promise, Array или Iterable. при подписке (C: \ Users \ andri \ OneDrive \ Desktop \ devfox \ autorent \ ng-videocms \ dist \ autorent \ server \ main. js: 1: 2547459) при подписке ToResult (C: \ Users \ andri \ OneDrive \ Desktop \ devfox \ autorent \ ng-videocms \ dist \ autorent \ server \ main. js: 1: 2775326) на CatchSubscriber.error (C: \ Users \ andri \ OneDrive \ Desktop \ devfox \ autorent \ ng-videocms \ dist \ autorent \ server \ main. js: 1: 1997435) в Observable_Observable._trySubscribe (C: \ Users \ andri \ OneDrive \ Desktop \ devfox \ autorent \ ng-videocms \ dist \ autorent \ server \ main. js: 1: 1952954) в Observable_Observable.subscribe (C: \ Users \ andri \ OneDrive \ Desktop \ devfox \ autorent \ ng-videocms \ dist \ autorent \ server \ main. js: 1: 1952574) на CatchOperator.call (C: \ Users \ andri \ OneDrive \ Desktop \ devfox \ autorent \ ng-videocms \ dist \ autorent \ server \ main. js: 1: 1996823) на Observable_Observable .subscribe (C: \ Users \ andri \ OneDrive \ Desktop \ devfox \ autorent \ ng-videocms \ dist \ autorent \ server \ main. js: 1: 1952428) в _task (C: \ Users \ Андри \ OneDrive \ Desktop \ devfox \ autorent \ ng-videocms \ dist \ autorent \ server \ main. js: 1: 1751796) в Observable_Observable.Observable.a.observer [как _subscribe] (C: \ Users \ andri \ OneDrive \ Desktop \ devfox \ autorent \ ng-videocms \ dist \ autorent \ server \ main. js: 1: 1752141) в Observable_Observable._trySubscribe (C: \ Users \ andri \ OneDrive \ Desktop \ devfox \ autorent \ ng -videocms \ dist \ autorent \ server \ main. js: 1: 1952792)

Как я уже исследовал, мое приложение при запуске выполняет 2 вызова API:

app.component.ts:

ngOnInit(){
get1();
get2();
}

  get1() {
    const loc = this.locationService.getPickupLocations().subscribe((data: Location[]) => {
      this.pickupLocations = data;
      this.formGroup.get(LocationFields.pickup).setValue(data[0].getId());
      this.pickupLocationsList = this.pickupLocations.map((data): ISelectOption => {
        return {
          label: data.getName(),
          value: data.getId(),
        };
      });
    },
    (error)=> {
      console.log(error)
    },
    () => {
      this.subs.add(loc);
      this.pickupDateChange(this.formGroup.get(this.LocationFields.pickupDate).value);
    });
  }


  get2() {
    const drop = this.locationService.getDropOffLocations().subscribe((data: Location[]) => {
      this.dropoffLocations = data;
      this.formGroup.get(LocationFields.dropoff).setValue(data[1].getId());
      this.dropoffLocationsList = this.dropoffLocations.map((data): ISelectOption => {
        return {
          label: data.getName(),
          value: data.getId(),
        };
      });
    },(error)=> {
      console.log(error)
    },
    () => {
      this.subs.add(drop);
    });
  }

LocationService.ts:

  static locationsEndpoint = 'public/locations/rental';
  getPickupLocations(): Observable<Location[]> {
    const reqHeader = new HttpHeaders({ 'Content-Type': 'application/json', 'No-Auth': 'True' });
    return this.http.get(`${LocationsService.locationsEndpoint}/pickup`, { headers: reqHeader }).pipe(
     map((data: ILocationResponse) => this.hydrateCollectionData(data, LocationsHydrator))
    );
  }

  getDropOffLocations(): Observable<Location[]> {
    const reqHeader = new HttpHeaders({ 'Content-Type': 'application/json', 'No-Auth': 'True' });
    return this.http.get(`${LocationsService.locationsEndpoint}/dropoff`, { headers: reqHeader }).pipe(
     map((data: ILocationResponse) => this.hydrateCollectionData(data, LocationsHydrator))
    );
  }

И перехватчики:

 private static BASE_URL = environment.apiUrl;

  readonly HEADER_AUTHORIZATION = 'Authorization';
  readonly HEADER_ACCEPT = 'Accept';
  readonly HEADER_CONTENT_TYPE = 'Content-Type';
  readonly ACCEPT_LANGUAGE = 'Accept-Language';

  constructor(
    private authService: AuthService,
    private localeService: LocaleService
  ) { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (req.headers.get('skip')) {
          return next.handle(req);
    }
    if (req.url.startsWith('./assets')) {
      return next.handle(req);
    }
    req = req.clone({
      url: this._prefixUrl(req.url)
    });

    req = req.clone({
      headers: req.headers.set(this.HEADER_ACCEPT, 'application/json')
    });

    req = req.clone({
      headers: req.headers.set(this.HEADER_CONTENT_TYPE, 'application/json')
    });

    req = req.clone({
      headers: req.headers.set(this.ACCEPT_LANGUAGE, this.localeService.getLocale())
    });

    // Set token if exists
    const token = this.authService.getToken();

    if (token) {
      req = req.clone({
        headers: req.headers.set(this.HEADER_AUTHORIZATION, `Bearer ${token}`)
      });
    }

    return next.handle(req).pipe(
      catchError((httpErrorResponse: HttpErrorResponse) => {
        if(httpErrorResponse.error !== undefined){
          const customError: ApiErrors = {
            name: httpErrorResponse.error.name,
            message: httpErrorResponse.error.message,
            errors: httpErrorResponse.error.errors
          };
          return throwError(customError);
        }
      })
    );
  }

  private _prefixUrl(path: string): string {
    if (path.indexOf('/') === 0) {
      path = path.substr(1, path.length - 1);
    }

    return `${Interceptor.BASE_URL}/${path}`;
  }

Я пытался без этих вызовов , попытался прокомментировать один из них.

Когда я отключаю эти звонки (комментировать их), приложение работает нормально.

Когда я позвоню им позже, после того как я их прокомментирую, (onclick), приложение работает нормально.

Когда я отключаю перехватчики, он работает (ТАК в них проблема, что изменить ??)

Как это исправить? И почему это происходит?

1 Ответ

1 голос
/ 07 апреля 2020

Трассировка указывает на то, что проблема связана с CatchOperator.

Я вижу только одно место, где в вашем коде используется оператор catchError

return next.handle(req).pipe(
      catchError((httpErrorResponse: HttpErrorResponse) => {
        if(httpErrorResponse.error !== undefined){
          const customError: ApiErrors = {
            name: httpErrorResponse.error.name,
            message: httpErrorResponse.error.message,
            errors: httpErrorResponse.error.errors
          };
          return throwError(customError);
        }
      })
    );

В вашем коде кажется, вы предполагаете, что функция, переданная в catchError, всегда будет получать экземпляр HttpErrorResponse, что не соответствует действительности. catchError будет использоваться для любой ошибки, поэтому переданная ей функция может получать ошибки любого типа.

Что произойдет, если httpErrorResponse.error равно нулю , но у вас все еще есть ошибка в Наблюдаемые где-то вверх по течению? Согласно приведенному выше коду, вы ничего не возвращаете, поэтому это может быть причиной того, что в журнале написано You provided 'undefined' where a stream was expected.

Вместо того, чтобы ничего не делать, вы можете выдать ошибку, чтобы получить подробности ошибки, вызвавшей тот факт, что вы вводите catchError оператор, так что-то вроде этого

  catchError(err => {
    if(error instanceof HttpErrorResponse && httpErrorResponse.error !== undefined){
      const customError: ApiErrors = {
        name: httpErrorResponse.error.name,
        message: httpErrorResponse.error.message,
        errors: httpErrorResponse.error.errors
      };
      return throwError(customError);
    } else {
      throw err
    }
  })
);
...