Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I have a service in my angular2 app called HttpClient This service is supposed to add an authorization header to each request the application is sending to my endpoints.
import { Injectable } from '#angular/core';
import { Headers, Http, Response, } from '#angular/http';
import { Router } from '#angular/router';
import { ErrorService } from '../../services/error/error.service'
#Injectable()
export class HttpClient {
private token: string;
private error: any;
private webApi = 'http://localhost:8080/api/v1/'; // Url to web api
constructor(
private http: Http,
private router: Router,
private errorService: ErrorService) { }
get(url: string): Promise<Response> {
return this.http.get(this.webApi + url, this.createAuthorizationHeader())
.toPromise()
.catch((e) => this.handleError(e));
}
post(url: string, data: any): Promise<Response> {
return this.http.post(this.webApi + url, JSON.stringify(data), this.createAuthorizationHeader())
.toPromise()
.catch((e) => this.handleError(e));
}
put(url: string): Promise<Response> {
return this.http.get(this.webApi + url, this.createAuthorizationHeader())
.toPromise()
.catch((e) => this.handleError(e));
}
delete(url: string): Promise<Response> {
return this.http.delete(this.webApi + url, this.createAuthorizationHeader())
.toPromise()
.catch((e) => this.handleError(e));
}
private handleError (error: any) {
var status: number = error.status;
if (status == 415) {
this.errorService.setError(error);
}
let errMsg = (error.message)
? error.message
: status
? `${status} - ${error.statusText}`
: 'Server error';
console.error(errMsg); // log to console instead
return Promise.reject(errMsg);
}
private createAuthorizationHeader() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
if (localStorage.getItem('token'))
this.token = localStorage.getItem('token');
headers.append('Authorization', 'Bearer ' + this.token);
return headers;
}
}
Also this service is setting an error to another custom service called ErrorService
import { Injectable, EventEmitter } from '#angular/core';
#Injectable()
export class ErrorService {
error: any;
public errorAdded$: EventEmitter<any>;
constructor() {
this.errorAdded$ = new EventEmitter();
}
getError(): any {
return this.error;
}
setError(error: any) {
alert('is not going to be called');
this.error.error = error;
this.errorAdded$.emit(error);
}
}
Those services are going to be bootstrapped in my main.ts
...
import { ErrorService } from './services/error/error.service';
import { HttpClient } from './services/http/http.service';
...
bootstrap(AppComponent, [
appRouterProviders,
HTTP_PROVIDERS,
ErrorService,
HttpClient,
....
]);
Now I want to display this error in my header component. So overtime an error occurred this error is going to be displayed in a separated box in my header.
The Problem is that my ErrorService.setError(error) method called in HttpClient.handleError won't get even fired.
.catch(this.handleError);
should be
.catch((e) => this.handleError(e));
to retain the scope of this.
where (e) is the parameter list
Alternatively you can use
.catch(this.handleError.bind(this));
Related
im tryng to get the response from this http.get
getChatId(emailTo): any {
var email = emailTo
const httpOptions = {
headers: new HttpHeaders({
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': this.token_value
})
};
this.httpClient.get("https://xxxx=" + email, httpOptions)
.subscribe(data => {
console.log(data['_body']);
return data
}, error => {
console.log(error);
return error
});
}
this inside my constructor
this.getChatId(this.emailTo).then((date) => {
var docRef = firebase.firestore().collection("xxx").doc(date.response);
docRef.onSnapshot((doc) => {
this.document = doc.data()
let chats_message = [];
for (let k in this.document.messages) {
chats_message.push(this.document.messages[k]);
}
chats_message.sort(function (a, b) { return a.id - b.id; })
this.messages_chat = chats_message;
this.content.scrollToBottom(300);//300ms animation speed
console.log("Array", this.messages_chat);
})
});
but it give me this error:
vendor.js:1823 ERROR Error: Uncaught (in promise): TypeError: Cannot
read property 'subscribe' of undefined TypeError: Cannot read property
'subscribe' of undefined
Subscribe is not a function in httpclient while the request. please follow the below code
import { Component } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '#angular/common/http';
#IonicPage()
#Component({
selector: 'page-sample',
templateUrl: 'sample.html',
})
export class SamplePage {
sampleDatas: Observable<any>;
constructor(public navCtrl: NavController, public httpClient: HttpClient) {
this.films = this.httpClient.get('https://swapi.co/api/films');
this.sampleDatas
.subscribe(data => {
console.log('my data: ', data);
})
}
You should rewrite your function as an Observable to interact with the httpclient. Preferably in a service file like ChatService. You can design the http request with models or any types you receive or send.
export class ChatService {
constructor(private http: HttpClient) {}
getChatId(emailTo: string): Observable<any> {
return this.httpClient.get<any>("https://xxxx=/" + email);
}
}
Call the http request on a page with the service injected in the constructor.
constructor(private chatService: ChatService) {}
getChatId() {
this.chatService.getChatId(this.emailTo).subscribe(
result => {
// do something with result
},
error => {
// do something with error
}
);
}
EDIT
If you work with models to pass and receive data in the http request, you can define them as type. https://blog.angular-university.io/angular-http/
import { User } from '../models/user';
export class ChatService {
constructor(private http: HttpClient) {}
getChatId(emailTo: string): Observable<User> {
return this.httpClient.get<User>("https://xxxx=/" + email);
}
}
I am trying to get a product from a local server using an angular2 rest service. When I do the GET I get the following error. I can get the item from the server using the Insomnia rest client so I know the issue is not with the server. i've also checked the url and made sure there's no errors there. Any idea what else I can check? i'm using ng-cli to run the app...
my error:
http://10.60.160.34/BRMServices/WebEnquiry//POSEnquiry/293
Failed to load resource: net::ERR_CONNECTION_RESET
app.component.ts:32
failureServer error
my rest service:
import { Injectable } from '#angular/core';
import { Http, Headers, Response, RequestOptions } from "#angular/http";
import { Observable } from "rxjs/Rx";
import { ProductModel } from "../models/product.model";
//import 'rxjs/add/operator/map';
//import 'rxjs/add/operator/catch';
//import 'rxjs/add/observable/throw'
#Injectable()
export class RestService {
public API_URL: string = "http://10.60.160.34/BRMServices/WebEnquiry/";
private headers: Headers;
private options: RequestOptions;
constructor(private http: Http){
this.init();
}
init() {
this.headers = new Headers({ 'Content-Type': 'application/json' });
this.options = new RequestOptions({ headers: this.headers });
}
getProduct(barcode: string): Observable<ProductModel> {
return this.http.get(this.API_URL + "/POSEnquiry/" + barcode, this.options)
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
}
my app.component.ts:
import { Component } from '#angular/core';
import { RestService } from "./services/rest.service";
import { ProductModel } from "./models/product.model";
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
product: ProductModel;
constructor(private restService: RestService){}
submitBarcode(barcode: HTMLInputElement){
this.restService.getProduct(barcode.value)
.subscribe((res) => {
//product = res;
console.log(res);
}, (res) => {
console.log("failure" + res);
});
//console.log("product: " + product);
}
}
It turned out to be the RequestOptions variable. When I replaced options with headers in the get request it worked with no issues...
I learn Angular2 and now i try to get my data from a rest service. My rest service works and i can get data from there.
But angular always give my this error message: JSON.parse: unexpected character at line 1 column 1 of the JSON data
This is my Service:
import { Injectable } from '#angular/core';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import { Person } from '../_models/person';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class PersonService {
private headers: Headers;
constructor(private http: Http)
{
this.headers = new Headers();
this.headers.append('Content-Type', 'application/json');
this.headers.append('Accept', 'application/json');
}
getPersons(): Observable<Person[]> {
return this.http.get('http://localhost:54612/api/Person')
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
private handleError(error: Response | any) {
// In a real world app, we might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
This is the component for the view:
import { Component, OnInit } from '#angular/core';
import { Person } from '../_models/person';
import { PersonService } from '../_services/person.service';
#Component({
moduleId: module.id,
templateUrl: 'login.component.html',
providers: [ PersonService ]
})
export class LoginComponent implements OnInit {
errorMessage: string;
personen: Person[] = [];
constructor(private personService: PersonService) { }
ngOnInit() { this.getPersons(); }
getPersons() {
this.personService.getPersons()
.subscribe(
personen => this.personen = personen,
error => this.errorMessage = <any>error);
}
}
And this is my view:
<h1>Tour of Heroes</h1>
<h3>Heroes:</h3>
<ul>
<li *ngFor="let person of personen">{{person.IDPerson}}</li>
</ul>
<p class="error" *ngIf="errorMessage">{{errorMessage}}</p>
Your server is return XML. The reason is probably because it's the default when you don't explicitly set the Accept to something else. You have set it in the Headers to JSON, but you never add the headers to the request. You need to do
this.http.get('http://localhost:54612/api/Person', { headers: this.headers });
Try this snippet, in your getPersons()
return this.http.get('http://localhost:54612/api/Person',{headers: this.headers })
.map((response:Response) => response.json())
I'm building an observable data service based on the following article: https://coryrylan.com/blog/angular-2-observable-data-services
In the article he used an array as an example, here I will use the user object since I'm developing the user service.
Here's what I got:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Events, SqlStorage, Storage } from 'ionic-angular';
import { Subject } from 'rxjs/Subject';
export interface DataStore {
user: Object
}
#Injectable()
export class UserService {
private baseUrl: string;
private storage: Storage;
private _user$: Subject<Object>;
private dataStore: DataStore;
constructor(
private http: Http
) {
this.baseUrl = 'http://localhost:3000';
this.storage = new Storage(SqlStorage);
this._user$ = <Subject<Object>>new Subject();
this.dataStore = {
user: { name: '' }
};
}
set user$(user: Object) {
this.storage.set('user', JSON.stringify(user));
this.dataStore.user = user;
this._user$.next(this.dataStore.user);
}
get user$() {
return this._user$.asObservable();
}
loadUser() {
return this.storage.get('user').then(
((user: string): Object => {
this.dataStore.user = JSON.parse(user);
this._user$.next(this.dataStore.user);
return this.dataStore.user;
})
);
}
login(accessToken: string) {
return this.http
.post('http://localhost:3000/login', { access_token: accessToken })
.retry(2)
.map((res: Response): any => res.json());
}
logout(): void {
this.storage.remove('user');
}
}
To authenticate I call the login() function and set the user data if everything ok.
this.userService.login(this.data.accessToken)
.subscribe(
(user: Object) => {
this.userService.user$ = user;
this.nav.setRoot(EventListComponent);
},
(error: Object) => console.log(error)
);
I feel it is better set the user data inside the service. I could do the following:
login(accessToken: string) {
return this.http
.post('http://localhost:3000/login', {
access_token: accessToken
})
.retry(2)
.map((res: Response): any => res.json())
.subscribe(
(user: Object) => {
this.userService.user$ = user;
this.nav.setRoot(EventListComponent);
},
(error: Object) => console.log(error)
);
}
But I won't be able to subscribe to the login() function in the component since it's already subscribed. How could I redirect the user if everything ok or show an alert if anything goes wrong in the component but setting the user inside the service?
In the main component I load the user data and set the rootPage:
this.userService.loadUser().then(
(user: Object) => this.rootPage = EventListComponent,
(error: Object) => this.rootPage = LoginComponent
);
I thought that calling the loadUser() function at this time I would not have to call it again, but I have to call it in all components that I need the user data:
this.user = this.userService.user$;
this.userService.loadUser();
I don't think the service is the way it should, what could I improve? Is there any better way to achieve what I want? Any example or idea?
I have a main component with 2 sub-components (update, profile).
On update component, I have a form with several input fields. When I submit a form, profile section information should update after a successful request.
The problem is, profile information doesn't update after a successful request.
So, how to invoke profile component to refresh updated data? I tried to call a service after successful request, but no luck.
By the way, parent service looks like:
#Injectable()
export class AvailabilityService {
constructor(private http: Http) {
}
getProfile() {
return this.http.get(API_URL + '/user/profile')
.map(this.extractData)
.catch(this.handleError);
}
freeOwnersParking(availableDates: AvailableDates) {
let domain = API_URL + '/parking/availability';
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
let body = JSON.stringify(availableDates);
return this.http.put(domain, body, options)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body;
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
return Observable.throw(errMsg);
}
}
UPDATE
Get profile:
getProfile() {
this.availabilityService.getProfile()
.subscribe(
profile =>this.profile = profile,
error => this.errorMessage = <any>error
);
}
Update profile:
freeOwnersParking() {
this.availabilityService.freeOwnersParking(this.availableDates)
.subscribe(
response => this.availabilityService.getProfile(),
error => this.errorMessage = error
);
}
You need to leverage a shared service between them to notify the profile component.
For example an UpdateProfileService with an observable / subject in it. In this case, the profile component can subscribe on it to be notified.
Here is the service:
#Injectable()
export class UpdateProfileService {
profileUpdated:Subject<boolean> = new Subject();
(...)
updateProfile(profile:any) {
return this.http.put('http://...', profile)
.map(res => {
this.profileUpdated.next(true);
return res.json();
});
}
}
and within the profile component:
#Component({
(...)
})
export class ProfileComponent {
constructor(private service:UpdateProfileService) {
this.service.profileUpdated.subscribe(() => {
// Update bound data for profile
});
}
}