Hasani
Hasani

Reputation: 3889

"Error-ReferenceError-ErrorEvent is not defined" for NativeScript app

I am a new learner of NativeScript. I am following a video tutorial on Coursera to create an Android project using NativeScript, and I got the above error that is made by this part of my code:

process-httpmsg.service.ts :

import { Injectable } from '@angular/core';

import { throwError } from 'rxjs';
import { HttpErrorResponse } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class ProcessHTTPMsgService {

  constructor() { }

  public handleError(error: HttpErrorResponse | any) {
    let errMsg: string;

    if (error.error instanceof ErrorEvent) {
      errMsg = error.error.message;
    } else {
      errMsg = `${error.status} - ${error.statusText || ''} ${error.message}`;
    }

    return throwError(errMsg);
  }
}

dish.services.ts:

import { Injectable } from '@angular/core';
import { Dish } from '../shared/dish';

import { Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { baseURL } from '../shared/baseurl';
import { ProcessHTTPMsgService } from './process-httpmsg.service';

@Injectable({
  providedIn: 'root'
})
export class DishService {

  constructor(private http: HttpClient,
    private processHTTPMsgService: ProcessHTTPMsgService) { }

  getDishes(): Observable<Dish[]> {
    return this.http.get<Dish[]>(baseURL + 'dishes')
      .pipe(catchError(this.processHTTPMsgService.handleError));
  }

  getDish(id: string): Observable<Dish> {
    return this.http.get<Dish>(baseURL + 'dishes/' + id)
      .pipe(catchError(this.processHTTPMsgService.handleError));
  }

  getFeaturedDish(): Observable<Dish> {
    return this.http.get<Dish[]>(baseURL + 'dishes?featured=true').pipe(map(dishes => dishes[0]))
      .pipe(catchError(this.processHTTPMsgService.handleError));
  }
}

menu.component.html:

<ActionBar title="Menu" class="action-bar">
</ActionBar>
<StackLayout class="page">
    <ListView [items]="dishes" class="list-group" *ngIf="dishes">
        <ng-template let-dish="item">
            <StackLayout orientation="horizontal" class="list-group-item">
                <Image row="0" col="0" rowSpan="2" height="108" width="108"  [src]="BaseURL + dish.image" class="thumb p-16"></Image>
                <GridLayout class="list-group-item" rows="auto *" columns="*">
                    <Label row="0" col="0" [text]="dish.name" class="list-group-item-heading"></Label>
                    <Label row="1" col="0" class="list-group-item-text" [text]="dish.description"></Label>   
                </GridLayout>
            </StackLayout>
        </ng-template>
    </ListView>
    <ActivityIndicator busy="true"  *ngIf="!(dishes || errMess)" width="50" height="50" class="activity-indicator"></ActivityIndicator>
    <Label *ngIf="errMess" [text]="'Error: ' + errMess"></Label>
</StackLayout>

menu.component.ts:

import { Component, OnInit, Inject } from '@angular/core';
import { Dish } from '../shared/dish';
import { DishService } from '../services/dish.service';


@Component({
  selector: 'app-menu',
  moduleId: module.id,
  templateUrl: './menu.component.html',
  styleUrls: ['./menu.component.css']
})
export class MenuComponent implements OnInit {

  dishes: Dish[];
  errMess: string;

  constructor(private dishService: DishService,
    @Inject('baseURL') private baseURL) { }

  ngOnInit() {
    this.dishService.getDishes()
      .subscribe(dishes => this.dishes = dishes,
        errmess => this.errMess = <any>errmess);
  }

}

I don't know which other parts of the project's code is needed to put, so let me know that please.

EDIT: baseURL.ts:

// export const baseURL = "http://localhost:3000/";

export const baseURL = "http://192.168.1.5:3000/";

Upvotes: 2

Views: 3631

Answers (3)

RcoderNY
RcoderNY

Reputation: 1764

His code is straight from the Angular docs and his problem with error.error instanceof ErrorEvent is not that ErrorEvent is an interface not a class. Please see the reference to the relevant Angular documentation at the end.

His actual problem is that ErrorEvent is a Web API, which is not implemented in a NativeScript environment. This means if you were running your code in a browser it would work perfectly fine.

It seems like in NativeScript, a HttpErrorResponse is always returned but if it is a client-side or network issue (where a ErrorEvent would usually be returned), it sets the status to "0", and the statusText to "Unknown Error".

Angular Docs:

Two types of errors can occur.

The server backend might reject the request, returning an HTTP response with a status code such as 404 or 500. These are error responses.

Something could go wrong on the client-side such as a network error that prevents the request from completing successfully or an exception thrown in an RxJS operator. These errors produce JavaScript ErrorEvent objects.

https://angular.io/guide/http#getting-error-details

private handleError(error: HttpErrorResponse) {
  if (error.error instanceof ErrorEvent) {
    // A client-side or network error occurred. Handle it accordingly.
    console.error('An error occurred:', error.error.message);
  } else {
    // The backend returned an unsuccessful response code.
    // The response body may contain clues as to what went wrong.
    console.error(
      `Backend returned code ${error.status}, ` +
      `body was: ${error.error}`);
  }
  // Return an observable with a user-facing error message.
  return throwError(
    'Something bad happened; please try again later.');
}

Upvotes: 2

MasterJedi
MasterJedi

Reputation: 1638

There are a few mistakes/ possible shortcoming in your code:

  1. As @Manoj answered error.error instanceof ErrorEvent should be replaced by error.error instanceof HttpErrorResponse

  2. Your menu.component.html uses [src]="BaseURL + dish.image" > it should be [src]="baseURL + dish.image" > as you injected baseURL

  3. You may need the nativescript wrapper for httpClient

import { NativeScriptHttpClientModule } from '@nativescript/angular/http-client';
@NgModule({
    imports: [
       ...
       NativeScriptHttpClientModule]
    ...
}]
  1. Make sure that your baseURL server allow connection from possibly unsecure sources.

  2. If you build nativescript app for Android check that your AndroidManifest.xml allows internet connections. Make sure the following are set:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    <application
        ...
        android:usesCleartextTraffic="true">

Upvotes: 1

Manoj
Manoj

Reputation: 21908

As I already mentioned you can not do error.error instanceof ErrorEvent as ErrorEvent is an interface not class. You could do error.error instanceof HttpErrorResponse.

You can not hit http://localhost:3000 from your Simulator / Emulator, you are suppose to hit your api by your machine's IP as they are in same network but technically different (simulated) devices.

Upvotes: 2

Related Questions