I was following a vue.js tutorial and saw something that confuses me and was wondering if someone can explain it to me since I never use promise. The below method is used to assign a customer array object. Why use a Promise? I thought Promise should be used when you are returning an object to a service consumer? Why and when should I use a promise?
loadCustomer() {
new Promise((resolve, reject) => {
axios.get(this.DetailsDataUrl)
.then(res => {
this.Customer = res.data
resolve()
})
.catch(err => {
console.log(err);
reject()
})
});
}
With promises you can call asynchronous functions.
e.g. here when you want to use loadCustomer you can await until this function resolve or reject:
try {
// resolve
const response = await loadCustomer()
} catch(err) {
// reject
console.log(err)
}
axios it self return a promise:
so you can rewrite your function like this:
loadCustoemr() {
return axios.get(this.DetailsDataUrl)
}
and call it:
loadCutomer()
.then(res => this.Customer = res.data)
.catch(err => console.log(err))
as above you can also use async/await here.
for more information you can use this link,
Related
It is to my understanding that callback functions are asynchronous and cannot return a value like regular functions. Upon reading about promises, I thought I grasped a good understanding about them, that they are basically an enhanced version of callbacks that allows returning a value like asynchronous function. In my getConnections method, I am attempting to call the find() function on my database through mongoose, and I am attempting to grab this array of objects and send it to the views.
var test = new Promise((resolve, reject) => {
Database.find().then(list => {
resolve(list);
}).catch(err=> {
return reject(err);
})
})
console.log(test)
When I attempt to log to the console outside of the promise function, I get Promise { _U: 0, _V: 0, _W: null, _X: null }
I don't think this is functioning correctly, and I thought I utilized promises correctly. Could anyone point me in the right direction on how to return this array of objects outside of the callback function?
You can simply add await before the promise declaration.
i.e.
var test = await new Promise...
The thing is that when you write a function like this:
const getData = async () => { const response = await fetch(someUrl, {}, {}); return response;}
Then you also need to await that function when you call it. Like this:
const setData = async () => { const dataToSet = await getData(); }
let test = new Promise((resolve, reject) => {
Database.find().then(list => {
resolve(list);
}).catch(err=> {
return reject(err);
})
})
test
.then(result=>console.log(result))
Should solve your problem.
var someValue;
var test = await new Promise((resolve, reject) => {
Database.find().then(list => {
resolve(list);
}).catch(err=> {
return reject(err);
})
}).then(res => {
someValue=res;
})
console.log(someValue);
There seems to be an extra then method
getUser () {
const options = {
credentials: 'include'
};
fetch("/api/user", options)
.then((response) => {
return response.json();
})
.then((results) => {
console.log(results);
})
.catch((err) => {
});
I would like to reduce to:
getUser () {
const options = {
credentials: 'include'
};
fetch("/api/user", options)
.then((response) => {
console.log(response.json());
})
.catch((err) => {
});
Wrather than just test it out and see if it works I would like to try and understand why it was written the first way an if it is good practice.
Update
Why are their two promises for only 1 asynchronous event?
Should not parsing JSON be a simple synchronous function call?
Or is this just a design choice that we can make any function asynchronous?
response.json() returns a promise. Their version logs out the result of that promise. Your version would log out the promise object in a pending state, not the value it resolves to.
This question already has answers here:
What is the explicit promise construction antipattern and how do I avoid it?
(3 answers)
Closed 3 years ago.
Axios is described as Promise-based, so is there a need for returning a new Promise when using Axios to query for data?
app.get('/api/nearbyRecommendations', async (req, res) => {
if(!req.query) return res.send({ error: 'Please enable location to get recommendations.' })
try {
const { longitude, latitude } = req.query
const locationName = await location.getLocationName(longitude, latitude)
res.send(locationName)
} catch (error) {
res.send(error)
}
})
I am making a GET request to the MapBox API, but I do not seem to ever get any errors despite setting up the catch block for my Axios request, even if I throw a new Error in the .then() block.
const getLocationName = async (latitude, longitude) => {
return new Promise((resolve, reject) => {
axios.get(`https://api.mapbox.com/geocoding/v5/mapbox.places/${longitude},${latitude}.json?access_token=${darkSkyAPIKey}`, {json: true})
.then(response => {
if(!response.data) return reject({ error: 'No location found.' })
resolve(response.data)
}).catch(error => {
reject(error)
})
})
}
If possible, do help and point out anything that may be altered to follow best practices.
You can just return the promise immeditately without using an async function:
const getLocationName = (latitude, longitude) => {
return axios.get(`https://api.mapbox.com/geocoding/v5/mapbox.places/${longitude},${latitude}.json?access_token=${darkSkyAPIKey}`, {json: true})
.then(response => {
if(!response.data)
throw Error('No location found.')
return response.data;
}).catch(error => {
console.log(error);
throw error;
})
}
Axios.get already returns a promise to you. If you also define the function as async that means that the returned promise will be wrapped in a promise again. So in your example you were triple wrapping the response in a promise. If you replace it with the getLocationName function with a regular function, usage in the first code snippet will remain exactly the same.
I am using fetch method to get some data from the server. Once I get that data, I need to store some of it (access_token to be more precise cause I am using oauth) in AsyncStorage. I tried doing just AsyncStorage.setItem without await, not how it is shown in https://facebook.github.io/react-native/docs/asyncstorage, and it worked just fine.
I changed it to:
fetch ('site/login', POST ...)
.then((response) => response.json())
.then(async(responseJson) => {
if (user.valid)
await AsyncStorage.setItem('access_token', responseJson.token);
And it works fine too. But I have 2 questions now:
Is my implementation with fetch and async correct?
And what might happen if I don't use await/async in this case?
Sorry, I am kinda new to Promises and Asynchronous methods in Javascript. Thanks!
async/await is just syntactic sugar over Promises. You're already using Promises, so there's no need to do that. Just return the Promise:
fetch ('site/login', POST ...)
.then((response) => response.json())
.then((responseJson) => {
if (user.valid) { // not sure where 'user' came from, but whatever
return AsyncStorage.setItem('access_token', responseJson.token);
} else {
throw new Error('Invalid user');
}
})
.then(_ => { // storage set, don't care about return value
// do stuff
})
.catch((err) => {
// handle error, including invalid user
});
Response to question in comments
The above in async/await would look like this:
async function foo() {
try {
const response = await fetch('site/login', POST ...);
const responseJson = await response.json();
if (user.valid) {
return await AsyncStorage.setItem('access_token', responseJson.token);
} else {
throw new Error('Invalid user');
}
} catch (error) {
// deal with errors
}
}
I don't know to to resolve this situation using JS promises.
Imagine I have some articles and I want to send a patch request to update them. I send one request per article. If the request of one article success then I update that article, but if the request fails, then I update the article differently. Also I want to show a message to the user informing if all the articles have been updated correctly or not.
This is not my real scenario and this may be a weird example. But it's what I want to accomplish in my React app.
Here is what I'm trying to do right now:
const saveArticles = articles => {
const promises = [];
articles.forEach(article => {
const promise = axios
.patch('/articles', article)
.then(() => updateArticleUi(article))
.catch(() => updateArticleUiWithError(article));
promises.push(promise);
});
Promise.all(promises)
.then(() => tellTheUserThereWasNoErrors())
.catch(() => tellTheUserThereWasSomeErrors());
};
This isn't working because the Promise.all is always executing the then callback, weather all promises succeed or not.
Thanks!
Your updateArticleUi and updateArticleUiWithErrors should have the respective return values so that you can distinguish whether there was an error or not when looking at the array of results:
function updateArticleUi(article) {
…
return {success: true};
}
function updateArticleUiWithError(article, error) {
…
return {success: false};
}
function saveArticles(articles) {
const promises = articles.map(article => {
return axios.patch('/articles', article).then(() =>
updateArticleUi(article)
, err =>
updateArticleUiWithError(article, err)
);
});
return Promise.all(promises).then(results =>
if (results.every(res => res.success)) {
tellTheUserThereWasNoErrors();
} else {
tellTheUserThereWasSomeErrors();
}
});
}
This works:
function axiosPatchRequest(url,data) {
return new Promise(function (resolve, reject) {
if (data) {
resolve(url);
} else {
reject('DATA_NOT_FOUND');
}
})
}
function updateArticleUi(data,article) {
return new Promise(function (resolve, reject) {
resolve({type:"updateArticleUi ",data,article});
})
}
function updateArticleUiWithError(data,article) {
return new Promise(function (resolve, reject) {
reject({type:"updateArticleUiWithError ",data,article});
})
}
function tellTheUserThereWasNoErrors(data){
console.log("tellTheUserThereWasNoErrors",data);
}
function tellTheUserThereWasSomeErrors(error){
console.log("tellTheUserThereWasSomeErrors",error);
}
const execute = (articles)=>{
const promises = [];
articles.forEach(article => {
const promise = axiosPatchRequest('/articles', article)
.then((data) => {
return updateArticleUi(data,article);
})
.catch((error) => {
return updateArticleUiWithError(error,article);
});
promises.push(promise);
});
Promise.all(promises)
.then((data) => tellTheUserThereWasNoErrors(data))
.catch((error) => tellTheUserThereWasSomeErrors(error));
};
execute(["one","","three"]);
execute(["one","two","three"]);
Promise.all will always call then because the promise you add to promises is already resolved one with either then or catch attached above
if you want to see catch to happen in .all chain just throw some exeption in updateArticleUiWithErro function
The problem is that you are catching the error thrown by
const promise = axios
.patch('/articles', article)
.then(() => updateArticleUi(article))
.catch(() => updateArticleUiWithError(article));
you should either throw a new error in the axios catch() or let the error bubble up by removing the catch from the axios call.