converting Promise to async await syntax problem - javascript

I want to convert promise in to async await but I cannot find the right syntax for the function that reads the data from the response
export async function getDataFromServer(id) {
try {
const resp = await fetch('/dataget', {
credentials: "same-origin",
mode: "same-origin",
method: 'POST',
headers: { "Content-Type": "application/json" },
body: `${id}`
})
const data = await resp.json()
const handel = await function (data) {
console.log(data);
// render function
renderDataFromServer(data)
}
}
catch (err) {
if (err === "server") return
console.log(err)
}
}

If you remove the unnecessary function declaration it should work:
export async function getDataFromServer(id) {
try {
const resp = await fetch('/dataget', {
credentials: "same-origin",
mode: "same-origin",
method: 'POST',
headers: { "Content-Type": "application/json" },
body: `${id}`
})
const data = await resp.json();
console.log(data);
// render function
return renderDataFromServer(data);
} catch (err) {
if (err === "server") return
console.log(err)
}
}

Related

what could be going wrong in this fetch?

I tried this solution to fetch data from multiple apis with async await but the output is undefined, what could be going wrong?
const getData = async (jwt) => {
try {
const [response1, response2, response3] = await Promise.all(
[
fetch("http://localhost:3000/api/confirmed"),
fetch("http://localhost:3000/api/deaths"),
fetch("http://localhost:3000/api/recovered"),
],
{
method: "GET",
headers: {
"user-agent": "vscode-restclient",
"content-type": "application/json",
accept: "application/json",
authorization:
"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibmFtZSI6IkxlYW5uZSBHcmFoYW0iLCJ1c2VybmFtZSI6IkJyZXQiLCJpYXQiOjE1OTY1MDY4OTN9.KDSlP9ALDLvyy0Jfz52x8NePUejWOV_mZS6cq4-JZXs",
},
}
);
const { data1 } = await response1.json();
const { data2 } = await response2.json();
const { data3 } = await response3.json();
console.log(data1, data2, data3);
} catch (err) {
console.error(`Error: ${err}`);
}
};
getData();
Promise.all only accepts a single parameter, an array of promises. Your second parameter (the object with method and headers) is therefore simply ignored. That obect needs to be passed as a second parameter to the fetch function, not to Promise.all.
Try the following:
const getData = async (jwt) => {
try {
const fetchOptions = {
method: "GET",
headers: {
"user-agent": "vscode-restclient",
"content-type": "application/json",
accept: "application/json",
authorization:
"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibmFtZSI6IkxlYW5uZSBHcmFoYW0iLCJ1c2VybmFtZSI6IkJyZXQiLCJpYXQiOjE1OTY1MDY4OTN9.KDSlP9ALDLvyy0Jfz52x8NePUejWOV_mZS6cq4-JZXs",
},
};
const [response1, response2, response3] = await Promise.all(
[
fetch("http://localhost:3000/api/confirmed", fetchOptions),
fetch("http://localhost:3000/api/deaths", fetchOptions),
fetch("http://localhost:3000/api/recovered", fetchOptions),
],
);
const { data1 } = await response1.json();
const { data2 } = await response2.json();
const { data3 } = await response3.json();
console.log(data1, data2, data3);
} catch (err) {
console.error(`Error: ${err}`);
}
};
getData();

TypeError: res.json is not a function (not able to get fetch data)

I m trying to GET response using fetch API not stuck in a error as I mentioned below. Here's my code
const DefaultLayout = () => {
let history = useHistory()
const callHomePage = async () => {
try {
const res = fetch('http://localhost:4000/api/authenticate', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-type': 'application/json',
},
credentials: 'include',
})
console.log(res)
const data = await res.json()
console.log(data)
if (!res.status === 200) {
const error = new Error(res.error)
throw error
}
} catch (err) {
console.log(err)
history.push('login')
}
}
Error: TypeError: res.json is not a function
Promise {} shows pending
const DefaultLayout = () => {
let history = useHistory()
const callHomePage = async () => {
try {
const res = await fetch('http://localhost:4000/api/authenticate', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-type': 'application/json',
},
credentials: 'include',
})
console.log(res)
const data = await res.json()
console.log(data)
if (!res.status === 200) {
const error = new Error(res.error)
throw error
}
} catch (err) {
console.log(err)
history.push('login')
}
}
You need to await the fetch statement and then call the .json method of the response.
const res = await fetch(...)
data = await res.json();
Read more: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

Async/Await in fetch() how to handle errors

I have stripe async code in my React app, and trying to add error handling in my code but have no idea how to handle it. i know how to do it with .then() but async/await is new to me
EDITED
added .catch() i got errors in network tab in response tab.
but i can log it to console?
submit = async () => {
const { email, price, name, phone, city, street, country } = this.state;
let { token } = await this.props.stripe
.createToken({
name,
address_city: city,
address_line1: street,
address_country: country
})
.catch(err => {
console.log(err.response.data);
});
const data = {
token: token.id,
email,
price,
name,
phone,
city,
street,
country
};
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}).catch(err => {
console.log(err.response.data);
});
console.log(response);
if (response.ok)
this.setState({
complete: true
});
};
thanks
Fetch detects only network errors. Other errors (401, 400, 500) should be manually caught and rejected.
await fetch("/charge/pay", headers).then((response) => {
if (response.status >= 400 && response.status < 600) {
throw new Error("Bad response from server");
}
return response;
}).then((returnedResponse) => {
// Your response to manipulate
this.setState({
complete: true
});
}).catch((error) => {
// Your error is here!
console.log(error)
});
If you are not comfortable with this limitation of fetch, try using axios.
var handleError = function (err) {
console.warn(err);
return new Response(JSON.stringify({
code: 400,
message: 'Stupid network Error'
}));
};
var getPost = async function () {
// Get the post data
var post = await (fetch('https://jsonplaceholder.typicode.com/posts/5').catch(handleError));
// Get the author
var response = await (fetch('https://jsonplaceholder.typicode.com/users/' + post.userId).catch(handleError));
if (response.ok) {
return response.json();
} else {
return Promise.reject(response);
}
};
You can either use try/catch just like normal, imperative programming:
try {
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
} catch(error) {
// Error handling here!
}
Or you can mix-and-match .catch() just like you do with promises:
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}).catch(function(error) {
// Error handling here!
});
Wrap your await with try catch.
try {
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
console.log(response);
} catch (error) {
console.log(error);
}
This works if server returns { message: "some error" } but I'm trying to get it to support res.statusText too:
const path = '/api/1/users/me';
const opts = {};
const headers = {};
const body = JSON.stringify({});
const token = localStorage.getItem('token');
if (token) {
headers.Authorization = `Bearer ${token}`;
}
try {
const res = await fetch(path, {
method: opts.method || 'GET',
body,
headers
});
if (res.ok) {
return await (opts.raw ? res.text() : res.json());
}
const err = await res.json();
throw new Error(err.message || err.statusText);
} catch (err) {
throw new Error(err);
}
async function loginWithRedirect(payload: {
username: string;
password: string;
}) {
const resp = await (await fetch(`${env.API_URL}/api/auth/login`, {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(payload),
credentials: "include",
})).json();
if (resp.error) {
dispatch({type: "ERROR", payload: resp.error.message});
} else {
dispatch({type: "LOGIN", payload: resp});
}
}
If response.ok is false you can throw an error then chain catch method after calling your function as follows
async function fetchData(){
const response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
if(!response.ok){
const message = `An error occured: ${response.status}`;
throw new Error(message);
}
const data = await response.json();
return data;
}
fetchData()
.catch(err => console.log(err.message));
I write promise function for using fetch in async await.
const promisyFetch = (url, options) =>
new Promise((resolve, reject) => {
fetch(url, options)
.then((response) => response.text())
.then((result) => resolve(result))
.catch((error) => reject(error));
});
By the way i can use it easly in async with try catch
const foo = async()=>{
try {
const result = await promisyFetch('url' requestOptions)
console.log(result)
} catch (error) {
console.log(error)
}
}
It was simple example, you could customize promisyFetch function and request options as you wish.
const data = {
token: token.id,
email,
price,
name,
phone,
city,
street,
country
};
axios
.post("/charge/pay", data)
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err.response.data);
});

How use await keyword along with asyncstorage setitem for server response?

I'm trying to use asyncstorage in my react native app.The problem is the server response I'm getting takes some delay so I want to wait for the response then I want to use that responseData.user_id to be saved in my app.I'm using nodejs as backend and mysql db.So after user registration I'm inserting it to db at the same time I've written another query for fetching their user_id (PK).So this responseData is getting to client and I'm trying to take that user_id from the response.So I've written something like this
onPressRegister = async () => {
try {
let response = await fetch('http://192.168.1.2:3000/users/registration', {
method: 'POST',
headers: {
'Accept': 'applictaion/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
contact: this.state.contact,
password: this.state.password,
})
});
let responseData = await response.json();
if (responseData) {
try {
Action.firstScreen();
await AsyncStorage.setItem('userid', JSON.stringify(responseData.userData.phone_no));
}
catch (e) {
console.log('caught error', e);
}
}
} catch (error) {
console.error(error)
}
}
And in my next screen I'm accessing the userid like this.And passing it the next API call like this.
getUserId = async () => {
let userId = await AsyncStorage.getItem('userid');
return userId;
}
onPressYes = (workType) => {
this.getUserId().then((userId) => {
this.setState({userId:userId})
})
fetch('http://192.168.1.2:3000/users/user_request',{
method:'POST',
headers:{
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
workType,
phone:this.state.userId
})
})
.then(response => response.json())
.then((responseData) => {
this.setState({
data:responseData
});
});
}
But this is the error I'm getting.
Try this:
onPressRegister = async () => {
try {
let response = await fetch('http://192.168.1.6:3000/users/registration', {
method: 'POST',
headers: {
'Accept': 'applictaion/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
contact: this.state.contact,
password: this.state.password,
})
});
let responseData = await response.json();
if (responseData) {
try {
await AsyncStorage.setItem('userid', JSON.stringify(responseData.user_id));
}
catch (e) {
console.log('caught error', e);
}
}
} catch (error) {
console.error(error)
}
}
To access the value in some other component:
getUserId = async () => {
let userId = await AsyncStorage.getItem('userid');
return userId;
}
componentWillMount() {
this.getUserId().then((userId) => {
console.log(userId);
})
}

Node + ES6: How to use Promise.all with async requests?

I have a method called fetchMerchantData which calls 3 other async methods. I'm trying to use Promise so that it doesn't call resp.direct(301, ...) until all the requests are finished but it's not working.
function fetchOauth2Token(authorizationCode, resp) {
...
request({
url: `https://connect.squareup.com/oauth2/token`,
method: "POST",
json: true,
headers: oauthRequestHeaders,
form: oauthRequestBody,
}, (error, oauthResp, body) => {
if (body.access_token) {
Promise.resolve(fetchMerchantData(body.access_token, body.merchant_id)).then(() => {
console.log("last!"); //<--------------------- this is printing first
resp.redirect(
301,
`myurl.com/blah`
);
});
;
} else {
// TODO find out what to do on failure
resp.redirect(301, `myurl.com/?error=true`);
}
})
}
function fetchMerchantData(access_token, merchant_id){
const updates = {};
request({
url: `https://connect.squareup.com/v1/me/locations`,
method: "GET",
json: true,
headers: {
Authorization: `Bearer ${access_token}`,
Accept: 'application/json',
"Content-Type": "application/json",
},
}, (error, response) => {
if (!error) {
const locations = response.body;
Promise.all([
saveMerchant(merchant_id, access_token, locations),
saveLocations(merchant_id, locations),
installWebhookForLocations(access_token, locations),
]).then(values => {
console.log("first!"); //<--------------------- this is printing last
return Promise.resolve("Success");
})
}
});
}
And here's an example of the saveMerchant method which calls firebase:
function saveMerchant(merchant_id, access_token, locations) {
const merchantRef = database.ref('merchants').child(merchant_id);
const location_ids = locations.map(location => location.id);
merchantRef.update({
access_token,
location_ids,
});
}
How would I synchronize this?
== UPDATE ==
This is how my installWebhookForLocations method looks:
function installWebhookForLocations(access_token, locations){
const locationIds = locations.map(location => location.id);
locationIds.forEach((locationId) => {
request({
url: `https://connect.squareup.com/v1/${locationId}/webhooks`,
method: "PUT",
json: true,
headers: {
Authorization: `Bearer ${access_token}`,
Accept: 'application/json',
"Content-Type": "application/json",
},
body: ["PAYMENT_UPDATED"],
}, (error) => {
if (!error){
console.log(`Webhook installed for ${locationId}`);
}
});
});
}
Here is an example of saveMerchant that would use a promise.
function saveMerchant(merchant_id, access_token, locations) {
return new Promise(function (resolve, reject) {
const merchantRef = database.ref('merchants').child(merchant_id);
const location_ids = locations.map(location => location.id);
merchantRef.update({
access_token,
location_ids,
}, function (error) {
if (error) return reject(error);
resolve();
});
});
}
To make the above easier, there is a nice Promise library called Bluebird, it has a promisify utility, that you could apply to firebird update method.
Also for your second question were your using forEach, bluebird has a nice utility function called map that you could use instead.

Categories

Resources