Reputation: 3889
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
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".
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.
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
Reputation: 1638
There are a few mistakes/ possible shortcoming in your code:
As @Manoj answered error.error instanceof ErrorEvent
should be replaced by error.error instanceof HttpErrorResponse
Your menu.component.html uses [src]="BaseURL + dish.image" >
it should be [src]="baseURL + dish.image" >
as you injected baseURL
You may need the nativescript wrapper for httpClient
import { NativeScriptHttpClientModule } from '@nativescript/angular/http-client';
@NgModule({
imports: [
...
NativeScriptHttpClientModule]
...
}]
Make sure that your baseURL
server allow connection from possibly unsecure sources.
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
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