How to catch when a promise fails? - javascript

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");
}

Related

issue accessing retrieved data from API which was pushed into a useState array - react ts

I am attempting to render data which was retrieved from my backend server.
The connection works fine and i'm able to retrieve a response.. My problem is that once I have loaded the information into my state-array, I cannot seem to access the properties within.
My useState array filled with the API request's data:
my backend's method i'm calling from my react program:
router.route("/api/issues").get(getAllIssues);
the route is calling the following function:
export const getAllIssues = async (
req: Request,
res: Response
): Promise<void> => {
try {
const issues: IssueInterface[] = await Issue.find({});
res.status(200).json({ issues });
} catch (err) {
throw err;
}
};
fetching the data from the api:
function Issues({ }: Props) {
const [issuesList, setIssuesList] = useState<IssueInterface[]>([]); // we retrieve from DB issues - we need it to look the same object's structure
useEffect(() => {
try {
axios({
method: 'get',
url: 'http://localhost:8001/api/issues',
headers: { 'Content-type': "application/json" }
}).then((response) => {
console.log(typeof (response))
const issuesStringified = JSON.stringify(response.data)
console.log("stringified: " + issuesStringified)
console.log(issuesList)
})
} catch (err) {
console.log("error : " + err);
}
}, [])
now my attempt to render parts of the array by using the following return function:
return (
<Stack>
<div>
{hasLoaded ? issuesList.map((issue: IssueInterface) => <div><h1>company: {issue.company_name}</h1></div>) : <></>}
</div>
</Stack>
)
provides the following outcome:
as if, it is unable to access the properties of each element.
any idea what am I doing wrong here?
regards! :_)

How can I delete some data from Firebase Realtime Database?

I have this functions to save and get data on it:
to save:
try {
const request = new Request('https://yandexmap-96969-default-rtdb.firebaseio.com/locations.json', {
method: 'post',
body: JSON.stringify(addNewLocation)
})
const response = await fetch(request)
window.location.reload()
return await response.json()
} catch (error) {
alert('Try again: ', error)
}
//to get:
try {
const request = new Request('https://yandexmap-96969-default-rtdb.firebaseio.com/locations.json', { method: 'get'})
const response = await fetch(request)
return await response.json()
} catch (error) {
alert('Try again: ', error)
}
And when I use "delete" instead of "get" it deletes the locations folder entirely, but when I use a link with a key at the end of the link, I get an error
You need make a DELETE request at the location you need to delete.
curl -X DELETE \
'https://[PROJECT_ID].firebaseio.com/locations.json'
const request = new Request('https://yandexmap-96969-default-rtdb.firebaseio.com/locations.json', { method: 'DELETE'})
const response = await fetch(request)
return await response.json()
I'm not sure about how your database structure looks like but the above request will delete the whole "locations" node. Here's an example:
If you want to delete only location2, then make a delete request at https://[PROJECT_ID].firebaseio.com/locations/location2.json
I'm not sure if there's any specific reason for you to use the REST API but you can try using Firebase Web SDK. It's easier to use, for example to delete location2:
firebase.database().ref("locations/location2").remove()
you can use the remove method
let userRef = this.database.ref('users/' + userId);
userRef.remove()
You can use the following code
deleteSomeData(id) {
fetch(
// don't add .json at [data Name]
`https://[your FireBase project url]/[data Name (don't add .json)]/${id}.json`,
{
method: 'Delete',
headers: {
'Content-Type': 'application/json',
},
}
)
.then((response) => {
if (response.ok) {
// if sucess do something
} else {
// if fail throw error
throw new Error('could not delete data');
}
})
.catch((error) => {
this.error = error.message;
console.log(id);
});
},
You can user item id to delete it like below.
const request = new Request('https://yandexmap-96969-default-rtdb.firebaseio.com/locations/<localtion_id>.json', { method: 'delete'})
your location id can be value like this, -MyB0qQoQuf9lPnwderfg

Try/catch. Try statement is given an error even when It's not failing

I'm trying to implement try/catch on javascript with Fetch API using PATCH Method. Most of the time when the fetch success I get a 400 (Bad Request) error and I don't know why, I wonder If I'm forgetting to add an if statement inside the try statement to check the response status before jumping into the catch statement. I also created a function called retry() to not allow the user to make more than 3 failing calls.
And if I make it fail I am not able to see the numberOfRetries log updated.
const retry = async (callback, numberOfRetries) =>
await callback(numberOfRetries)
export const updateValue = async (name, active, numberOfRetries = 0) => {
try {
await fetch(`${apiUrl}/device/${name}?active=${active}`, {
method: 'PATCH',
headers: {
Accept: 'application/json',
'Content-type': 'application/json; charset=UTF-8'
},
body: JSON.stringify({
name,
active
})
})
console.log('ok')
} catch (error) {
if (numberOfRetries >= 2) {
return
}
console.log(`retry number ${numberOfRetries}`)
return await retry(updateValue, ++numberOfRetries)
}
}
when the fetch is successfull I get a 400 (Bad Request) error and I don't know why, it's jumping into the catch statement.
No, the catch block doesn't run. The error you see in the devtools log is because a network request failed with an HTTP error code. You can disable the log messages in the console options.
As for why you are getting a 400 code, you have to check your serverside code - it suggests you are doing the request wrong.
I wonder If I'm forgetting to add an if statement inside the try statement to check the response status
Yes, you forgot that as well. You should check for the .ok property of the response:
export const updateValue = async (name, active, numberOfRetries = 0) => {
try {
const response = await fetch(`${apiUrl}/device/${name}?active=${active}`, {
// ^^^^^^^^^^^^^^
method: 'PATCH',
headers: {
Accept: 'application/json',
'Content-type': 'application/json; charset=UTF-8'
},
body: JSON.stringify({
name,
active
})
})
if (response.ok) {
// ^^^^^^^^^^^^^^^^
console.log('ok')
// console.log(await response.text()) or something
} else {
throw new Error("HTTP Error "+response.status);
}
} catch (error) {
if (numberOfRetries >= 2) {
return
// ^^^^^^ should be `throw error` instead of returning undefined?
}
console.log(`retry number ${numberOfRetries}`)
return updateValue(name, active, ++numberOfRetries)
// ^^^^^^^^^^^^^ pretty surely you'll want to pass through the arguments
}
}

Angular Observable not doing the put call

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');
});

React-native async fetch returns null

I am trying to put fetch functions into a separated file, so I can organise these API fetch easily. However, when I try to fetch and return the data, it gives me null or an unexpected json object. Here is part of my src:
//api.js
export async function LoginAPI(username, password) {
const url = baseURL + "/login/";
var params = {username: username, password: md5.hex_md5(password)};
let response = await fetch(url, {
method: 'POST',
headers: {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'},
body: JSON.stringify(params)
});
return await fetch(url, {
method: 'POST',
headers: header,
body: JSON.stringify(params)
})
.then((res) => res.text())
.then((text) => text.length ? JSON.parse(text) : {})
.catch((error) => {
throw error;
});
};
Here is the another file.
//index.js
var Login = React.createClass({
onPress_login: function() {
var value = this.refs.form.getValue();
if (value) {
result = LoginAPI(value.username, value.password);
console.log(result);
} else {
this.AlertDialog.openDialog();
}
},
render() {
return (
(...)
<Button onPress={this.onPress_login}>
<Text>Login</Text>
</Button>
The fetch is working, it is communicating with the server. However, the console log returns me this at the first place
Promise _45: 0_54: null _65: null _81: 1 __proto__: Object
I am assuming that the result log in the console at the first place is not the await result (the actual response from server, but an object of fetch response). I tried to search out methods online but I can't find any post/blog/article saying how to do fetch as a function call.
Is there any way to do like swift, LoginAPI(username, password, callback: {...}) please?
The problem is that you're are making an async function and not waiting for the response, the you see that kind of console log.
Try this:
result = await LoginAPI(value.username, value.password);
Let me know if this was your problem.

Categories

Resources