I use a spring boot with angular .right now is i have a method which allows to bring the data from api service every second but but a message that is displayed:
core.js:6185 ERROR TypeError: You provided 'undefined' where a stream
was expected. You can provide an Observable, Promise, Array, or
Iterable.
//service
ListAutombilesAuto(){
let headers=new HttpHeaders({'Authorization':this.jwt});
return this.fiches=this.http.get(this.BaseUrl+'/Automobiles',{headers:headers}).pipe
(
merge(this.fiches, interval(1000).pipe(switchMap(() => this.fiches)))
);
}
//component
ListAuto(){
this.auth.ListAutombilesAuto().subscribe(data=>{
this.fiches=data;
console.log(this.fiches);
}) // api call
}
is there any solutions?
thank you for help
You are referencing this.fiches within its first assignment, therefore its value is still undefined.
Try fix your code as following:
ListAutombilesAuto() {
let headers = new HttpHeaders({ 'Authorization': this.jwt });
this.fiches = this.http.get(this.BaseUrl + '/Automobiles', { headers: headers });
return this.fiches.pipe
(
merge(this.fiches, interval(1000).pipe(switchMap(() => this.fiches)))
);
}
But actually why not keep it simple:
ListAutombilesAuto() {
let headers = new HttpHeaders({ 'Authorization': this.jwt });
return timer(0, 1000)
.pipe(
switchMap(() => this.http.get(this.BaseUrl + '/Automobiles', { headers }))
)
}
Related
I've built an API using C# that uses JWT tokens for authorization. On the frontend I store these tokens in local storage and get them, when creating a request. When creating GET or DELETE requests, everything works fine, and using console.log() I can see that fetch options have the Authorization header added. However when using POST or PATCH methods, the Authorization header is missing immediatly after adding it to the object. Here is my request method:
const send = async (apiOptions: ApiParams): Promise<FetchReturn> => {
const accessToken = GetAccessToken()
const options: ApiOptions = {
method: apiOptions.method,
headers: {
Authorization: `Bearer ${accessToken}`
}
}
console.log(options)
if (apiOptions.data) {
options.headers = {
'Content-Type': 'application/json'
}
options.body = JSON.stringify(apiOptions.data)
}
const result = await fetch(`${getUrl()}/${apiOptions.path}`, options).then(res => res).catch(err => err)
if (!result.ok) {
if (IsExpired()) {
const refreshResult = await fetch(`${getUrl()}/api/user/refresh`, {method: 'POST', headers:{
'Content-Type': 'application/json'
}, body: JSON.stringify(GetRefreshRequest())}).then(res => res).catch(err => err)
if (refreshResult.ok) {
Login(JSON.parse(await refreshResult.text()))
return await send(apiOptions)
} else if (refreshResult.status === 401) {
Logout()
window.location.reload()
return { code: 0, text: ""}
}
}
}
const text = await result.text()
return { code: result.status, text: text }
}
I suppose that in apiParams for POST you have property 'data' assigned, and later you have if-condition that completely replaces request headers object.
Change it to:
options.headers['Content-Type'] = 'application/json';
To keep authorization in headers
The first time check your apiOptions.data
i think , its null when you call POST/Patch request
Just put console.log("...") In the if statement , Then try for resolve your Error
If your problem not resolved, put a replay under my post
Problem
My code is searching the database for a record and returns error when it cannot find an existing entry. It needs to check if the request is empty before parsing and return an empty array if it did not find a record and return [results] array if it does find one. How do I solve this problem?
This is for a Zapier integration with Zoho CRM that will search a custom module by Account_Name for an existing record and create one if it does not already exist.
Code
const options = {
url: `https://www.zohoapis.com/crm/v2/Accounts/search?criteria=(Account_Name:equals:${bundle.inputData.Account_Name})`,
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Zoho-oauthtoken ${bundle.authData.access_token}`,
'Accept': 'application/json'
},
params: {
}
}
return z.request(options)
.then((response) => {
response.throwForStatus();
const results = [z.JSON.parse(response.content)];
return [results];
});
You can try using a catch if your promise fails to resolve.
Like:
return z.request(options)
.then((response) => {
response.throwForStatus();
const results = [z.JSON.parse(response.content)];
return [results];
})
.catch(err => {
/*
check if the error is specifically where no entry in db was found.
Or if the error is always for that purpose
*/
console.log(err) // handle error approriately, maybe send to sentry?
return []; //emtpy array, when db errors out?
});
if response.content is null when it doesn't find anything:
.then((response) => {
...
return (response.content) ?
[z.JSON.parse(response.content)] :
Error("invalid request");
}
if response.content is an empty object when it doesn't find anything:
.then((response) => {
...
return (Object.keys(response.content).length) ?
[z.JSON.parse(response.content)]
: Error("invalid request");
}
i am calling alot of api's based on for loop and how can i keep track that all are successfully completed .
I know to how to keep track but that is working on for only one api'call..
So how can i get over this think that i get to know all api' call are completed successfully.
Here is the method of api that will be call several time by loop.
getpages(id) {
let url = ApiAddress.API_ENDPOINT + '/ads/publish/' + id + '/pages';
let token = localStorage.getItem('token');
let headers = new HttpHeaders()
.set('Content-Type', 'application/json')
.set('authorization', 'Bearer ' + token);
return this
.http
.get(url, {headers: headers})
}
And i subscribe it in that loop.How will i get to know all are completed successfully .so i can hide the loading bar
By reading the Angular 2 docs I assume that the http.get method returns a promise.
If you want to wait for all your requests to finish using this function you would want all the promises to finish - this is what Promise.all is for (=
And in code:
getpages(id) {
let url = ApiAddress.API_ENDPOINT + '/ads/publish/' + id + '/pages';
let token = localStorage.getItem('token');
let headers = new HttpHeaders()
.set('Content-Type', 'application/json')
.set('authorization', 'Bearer ' + token);
return this
.http
.get(url, {headers: headers})
}
const IDS_PROMISES = [1,2,3].map(id=>getPages(id)); // Enter your IDS
Promise.all(IDS_PROMISES).then(()=>{
// Here you can check the status of each request after they are ALL done.
})
You can catch errors on API calls by something like this:
return this.http.get(url, {headers: headers})
.catch( err => return Observable.throw( err ) );
On the subscribe method you can something like this:
this.getPages(id).subscribe( response => { console.log("success") },
( err ) => { console.log("error") } );
I am working on my first Angular app, but am having a problem going an http.put call. Here is the function I call:
updateUser(columns, values) : Observable<boolean> | boolean {
const headers: Headers = new Headers(); // Need to set content type
headers.append('Content-Type', 'application/json; charset=utf-8');
headers.append('Authorization', `Bearer ${this.authenticationService.token}`);
const options = new RequestOptions({ headers: headers });console.log('test service');
return this.http.put(`${API_URL}users/${this.authenticationService.userId}`, JSON.stringify({ columns: columns, values: values }) , options)
.map((response: Response) => {
console.log('test service1');return Observable.of(true);
})
.catch(e => {
console.log('test service2');return Observable.of(false);
});
When I call the function test service prints to the console, but test service1 and test service2 never print out. I checked my express backend and chrome dev tools and the app is never making the put call to the backend. There are no errors in the console either. So I am missing something, but can't figure it out.
Thank you for any help
Edit: I'm wondering if the issue is because I am just calling this function in another function:
saveColumns(){
this.userService.updateUser('home_columns',this.columns_show);
localStorage.setItem('columns_show', JSON.stringify(this.columns_show) );
}
for http.get functions, I typically do something like this:
loadStudents(page: number, grade = []) {
if (grade.length != 0){
this.student_query_filter = { key:'grade_level',value:grade.join('||') };
} else {
this.student_query_filter = {};
}
this.studentService.getStudentsCount([{ key: 'last_name', value: this.student_search_filter },this.student_query_filter])
.subscribe(
total => this.total = total, //Assign returned student count to local property
err => { console.log(err); });
}
You want to pass the data as an object instead of with JSON.stringify.
You want to return the result from map, not another Observable. If you did want to return a different observable you should change map to switchMap.
The signature should be Observable<boolean> as that is what you are returning.
Be sure to check the developer console in your browser to see if the request is being sent and what the response is. It might be something simple like putting together the URL incorrectly (missing a / for example)
updateUser(columns, values) : Observable<boolean> {
const headers: Headers = new Headers(); // Need to set content type
headers.append('Content-Type', 'application/json; charset=utf-8');
headers.append('Authorization', `Bearer ${this.authenticationService.token}`);
const options = new RequestOptions({ headers: headers });
console.log('test service, sending to: ' + `${API_URL}users/${this.authenticationService.userId}`);
return this.http.put(`${API_URL}users/${this.authenticationService.userId}`, { columns: columns, values: values }, options)
.map((response: Response) => {
console.log('test service1');
return true;
})
.catch(e => {
console.log('test service2');
return false;
});
}
Edit
If your caller is not going to do anything with the result and you do not care what that result is then do not return an Observable at all. Change the return signature to void and execute a subscribe after the call to log the result.
this.http.put(`${API_URL}users/${this.authenticationService.userId}`, { columns: columns, values: values }, options)
.subscribe((response: Response) => {
console.log('test service1'); }
, e => {
console.log('test service2');
});
I have a function that does a post request to the API, and gets back an object for a newly created document. I am successfully getting data back from the API in this function call, but while I am getting a new object with the correct "_id" info logged to the console, my "this.router.navigate(['/record', this._id])" is not triggering. I assume I should be able to tack it onto the end of this function like I am doing, so that it programmatically handles the navigation when the data is returned. But it's not working. The app doesn't navigate at all when that function is triggered. What am I missing here?
createRecord() {
this.recordsService.createRecord().subscribe(
data => {
// refresh the list
console.log(data);
return true;
},
error => {
console.error("Error creating record...");
return Observable.throw(error);
}
);
console.log('createRecord function initiated...');
this.router.navigate(['/record', this._id]);
}
My service looks like this:
createRecord() {
const headers = new Headers({ 'Content-Type': 'application/json' });
const options = new RequestOptions({ headers: this.headers });
const body = JSON.stringify({deleted: true});
return this._http.post
('https://api.somesite.com/v0/records?apikey=someapikey',
body, options).map((res: Response) => res.json());
}
Actually, you should call router.navigate when you successfully get your data (in the success callback)
createRecord() {
this.recordsService.createRecord().subscribe(
data => {
// refresh the list
this.router.navigate(['/record', data._id]);
},
error => {
console.error("Error creating record...");
return Observable.throw(error);
}
);
}