am relatively new to async tasks but I cant comprehend why my fetch API wont set my vue variable but on console.log it shows the Variable. I’ve tried Async/Await in vain. See the code segment below on my .vue component.
data(){
return{
pg:’’
}
},
methods:{
insertData(){
this.insertDataAPI()
console.log(this.pg) //THIS GIVES EMPTY STRING INSTEAD OF FETCHED DATA
},
insertDataAPI(){
fetch(‘EndPoint’, {
method:'POST',
headers:{
// some headers
},
body:JSON.stringify({
// some data
})
}).then( res => res.json())
.then(async page =>this.pg = await page //Console.log logs the page fine
// but variable pg is not set
).catch( (err) => {
console.log(err)
});
}
}
async/await is a different handler for promise.then().catch(). As fetch returns a promise you can use both
Option 1, await the fetch:
methods: {
insertData() {
this.insertDataAPI();
console.log(this.pg);
},
insertDataAPI() {
const response = await fetch(‘EndPoint’, {
method:'POST',
headers:{
// some headers
},
body:JSON.stringify({
// some data
})
});
this.pg = response.json();
}
}
Option 2, await the insertDataAPI:
methods: {
async insertData() {
await this.insertDataAPI();
console.log(this.pg);
},
insertDataAPI() {
return fetch(‘EndPoint’, {
method:'POST',
headers:{
// some headers
},
body:JSON.stringify({
// some data
})
}).then(res => res.json())
.then(page => this.pg = page)
.catch( (err) => {
console.log(err)
});
}
}
let's try to read about the way async/ await work
you can try on Axiost lib for easier to fetch APIs
Related
i'm using axios with vuex, i need to send data with json form to execute post request and add new row with axios, i'm using vuex, when action is trigered it doesn't keep the data and sent it on action, the data json is created on vue componment but don't send it to action to execute axios post :
Action.js:
export const addClassification = ({data}) => {
console.log('data actio:', {data})
axios
.post("/vendor/classification/save", data, {
headers: {
"Content-Type": "application/json",
// withCredentials: true //sent with cookie
Authorization: "Bearer " + Vue.$cookies.get("jwt"),
}
})
.then((res) => {
console.log('res', res)
// commit("ADD_TO_CLASSIFICATION", data);
})
.catch((err) => {
console.log(err);
});
state.js:
export default {
vendorClassificationList: [],
}
page.vue:
<BaseButton
label="Modifier"
classValue="btn-outline-primary"
#click.native="addClassificationData"
/>
data() {
return {
submitStatus: "",
name: this.$route.params.name,
id: this.$route.params.id,
code: this.$route.params.code,
jsonData:[]
};
},
methods: {
...mapActions(["addClassification"]),
addClassificationData() {
this.jsonData = JSON.stringify({
id: null,
name: this.name,
code:this.code,
active:true
})
console.log('json is', this.jsonData)
this.addClassification({
data : this.jsonData
})
},
Actions is Vuex receive the vuex context as the first param, as you can see in the docs.
In other words if you change in Action.js:
addClassification = ( {data}) => {
to
addClassification = (vuexContext, {data}) => {
it should do the trick. You can call the param vuexContext, context, destructure it if needed or call it _ if unused (as in your case), doesn't really matter, as long as it's there.
Your vuex action is wrong. You are missing the context which can use argument restructuring. Also, you probably need to send res.data within the commit instead of res, depending on what are you doing in your mutation.
actions: {
addClassification ({ commit }, payload) {
axios
.post("/vendor/classification/save", payload, {
headers: {
"Content-Type": "application/json",
// withCredentials: true //sent with cookie
Authorization: "Bearer " + Vue.$cookies.get("jwt"),
}
})
.then((res) => {
console.log('res', res)
commit("ADD_TO_CLASSIFICATION", res.data);
})
.catch((err) => {
console.log(err);
})
}
}
i have a problem i don't understand why i can't recover my recette.
My route at node is ok i have my good res ut at vue my code don't work my res is undefined.
What I am trying to do is to filter my recipes by retrieving only the recipes which have as category recipe 1. I made a route on node which works and which returns me exactly what I want but at the level of view i have a problem.
NODE.JS
router.get("/recette_light", (req, res) => {
db.cat_recette
.findOne({
where: { id: req.body.id },
include: { all: true },
})
.then((cat_recette) => {
if (cat_recette) {
res.status(200).json({
cat_recette: cat_recette,
});
} else {
res.json("il n'y a pas de cat_recettes");
}
})
.catch(err => {
res.json(err);
});
});
VUE.JS
<div>
<navbar_user />
<mylight :recette="recette" :user="user" />
<myfooter />
</div>
</template>
<script>
import navbar_user from "../components/navbar_user";
import mylight from "../components/light";
import myfooter from "../components/myfooter";
export default {
name: "",
data() {
return {
recette: "",
user: "",
};
},
components: {
navbar_user,
mylight,
myfooter,
},
created: function() {
this.axios
.get("http://localhost:3000/recette/rec_recette/:1")
.then((res) => {
(this.cat_recette.recette = res.data.recette),
this.axios
.get(
"http://localhost:3000/user/rec_user/" +
localStorage.getItem("email")
)
.then((res) => {
this.user = res.data.user;
});
});
},
};
Thank you for your help i'm novice
On the frontend, you are making an HTTP request with the GET method, which has no body. On the backend, req.body.id will be undefined because there is no request body in the first place.
So you have several options:
First: use a POST request on the front end
axios({
method: 'POST',
url:"http://localhost:3000/recette/rec_recette",
headers: {},
data: {
id: 'votre_id_ici', // This is the body part
}
});
The backend code to handle the post request:
(Use async/await to make the code cleaner)
router.post('/recette_light', async (req, res) => {
try {
// Assuming you are searching for your recette using MongoDB doc.id
const cat_recette = await db.cat_recette.findById(req.body.id);
// If there are no matching docs.
if (!cat_recette) {
return res.json("il n'y a pas de cat_recettes");
}
// Otherwise send the data to the frontend
res.status(200).json({ cat_recette: cat_recette, });
} catch (err) {
console.log(err);
res.status(500).json({ msg: 'Server Error', });
}
});
Second: use the GET method still but with URL parameters
axios.get("http://localhost:3000/recette/rec_recette/votre_id_ici")
The backend code to handle it:
// Note the /:id at the end
router.get('/recette_light/:id', async (req, res) => {
try {
// Assuming you are searching for your recette using MongoDB doc. id
// Note the req.params.id here not req.body.id
const cat_recette = await db.cat_recette.findById(req.params.id);
// If there are no matching docs.
if (!cat_recette) {
return res.json("il n'y a pas de cat_recettes");
}
res.status(200).json({ cat_recette: cat_recette, });
} catch (err) {
console.log(err);
res.status(500).json({ msg: 'Server Error', });
}
});
Vue.component('test', {
template: `some html`,
data() {
{
return {
somedata: 'hey, starting!'
}
}
},
methods: {
fetchdata: function fetchdata() {
fetch('http://localhost:5000/getmesome')
.then(response => response.json()).then(data => this.somedata = data
);
}
}, created() {
this.fetchdata();
console.log(this.somedata); //returns 'hey starting' not the fetched data.
}
});
As shown in the code comment, this is not refreshing the property with the fetched data. How can I do it?
Thanks.
fetchdata() will return immediately while the request is still in progress since it is an async operation. console.log(this.somedata) will be executed before the fetch operation has completed.
This is a basic async misunderstanding; I would suggest you read up on asynchronous JavaScript topics (promises, async and await, etc).
Either of these solutions will work:
methods: {
fetchdata() {
return fetch('http://localhost:5000/getmesome')
.then(response => response.json())
.then(data => this.somedata = data);
}
},
created() {
this.fetchdata()
.then(() => console.log(this.somedata));
}
methods: {
async fetchdata() {
const res = await fetch('http://localhost:5000/getmesome');
const data = await res.json();
this.somedata = data;
}
},
async created() {
await this.fetchdata();
console.log(this.somedata);
}
I created an array lists that contains a few strings.
Now I want to loop through lists (i.e., in getSubs()) and make an Axios request. This request should contain one string from lists each time.
My code:
computed: {
subscribers: {
get() {
return this.$store.state.subscribers;
},
set(value) {
this.$store.commit('updateSubscribers', value);
},
},
},
methods: {
getLodzkie() {
axios
.get(`correct_domain/lodzkietargi/get`)
.then((response) => {
this.subscribers = [];
this.subscribers.push.apply(this.subscribers, response.data)
})
.catch(function(error) {
console.log(error);
})
},
getSubs() {
function getSub(value) {
axios
.get(`correct_domain/${value}/get`)
.then((response) => {
this.subscribers.push.apply(this.subscribers, response.data)
})
.catch(function(error) {
console.log(error);
});
console.log(value);
}
this.lists.forEach(function(entry) {
getSub.call(null, entry);
});
},
getLodzkie() works beautifully
Thank You a lot #ourmandave. That helped me perfectly.
Rewrote function below:
getSubs() {
let listsReqs = this.lists.map(list => {
return axios.get(`correct_domain/${list}/get`);
});
axios.all(listsReqs)
.then(axios.spread((...responses) => {
responses.forEach(res => this.subscribers.push.apply(this.subscribers, res.data));
})
)},
I have a simple vue app where I'm trying to add simple authentication. Inside my login.vue, I use axios to authenticate the user via ajax and store the token returned by the api in the store then redirect to a new page (ex: dashboard.vue).
The problem is that the token is saved but the view is not updated, can't call router.push() ...
Any ideas why isn't it working ? Thanks
Login.vue
methods: {
authenticate () {
var dataLogin = {
email: this.login,
password: this.password
}
var headers = { headers: { 'Content-type': 'application/json', 'Accept': 'application/json' } }
axios.post(config.apiUrl, dataLogin, headers)
.then(response => {
this.$store.dispatch('login', response.data).then(() => {
// if there is no error go to home page
if (!this.$store.getters.error) {
this.$router.push('/')
}
})
})
.catch(error => {
this.errorMessage = error.response.data.message
this.authError = true
})
}
}
The store function just save the token with localStorage
const actions = {
login (context, data) {
context.commit('authenticate', data)
}
}
const mutations = {
authenticate (state, data) {
localStorage.setItem('user-access_token', data.access_token)
}
}
You are calling a then() handler when you dispatch the action.
But your action does not return a promise.
So return a promise in your action as follows:
const actions = {
login (context, data) {
return new Promise((resolve, reject) => {
context.commit('authenticate', data)
resolve()
})
}
}
Also chain your promises for better readability
axios.post(config.apiUrl, dataLogin, headers)
.then(response => {
return this.$store.dispatch('login', response.data)
}).then(() => {
// if there is no error go to home page
if (!this.$store.getters.error) {
this.$router.push('/')
}
})
.catch(error => {
this.errorMessage = error.response.data.message
this.authError = true
})