how to call multiple function in fetch hook in nuxt, vue - vuejs2

I facing issue with calling multiple function in the fetch hook nuxt provided getting error when I am calling 2 function from fetch with await.
async fetch() {
await this.fetchData();
await this.fetchData2();
},
methods: {
fetchData(lang) {
this.$store.dispatch('getData')
},
async fetchData2() {
let res = await api.getData2();
},
}
This is the flow I am using when the project run it giving error
TypeError: Cannot read property 'toLowerCase' of undefined and TypeError: progress.start is not a function
I am using nuxt progress for loading .Please let me know what I am doing wrong

You are awaiting this.fetchData(), but that is not returning a promise.
You want to add await this.$store.dispatch('getData'). You are also not making use of the lang param.
In other words, I guess the following would work...
async fetch() {
await this.fetchData();
await this.fetchData2();
},
methods: {
async fetchData() {
await this.$store.dispatch('getData')
},
async fetchData2() {
let res = await api.getData2();
},
}
(or even just returning this.$store.dispatch('getData') without fetchData being an async fn)

Related

Why do I receive PromiseĀ {<pending>} with Vuejs

I have a very simple two methods in Vuejs and it returns me promise pending what I am doing it's this:
TotalIncomeData(day, branch_office_id) {
return fetch('/api/collection/total/'+day+'/'+branch_office_id+'?api_token='+App.apiToken)
.then(response => {
return response.data;
}
);
},
getTotalIncomes(day, branch_office_id) {
console.log(this.TotalIncomeData(day, branch_office_id))
},
Why am I not getting the value? Thanks
You need to call .json() on the fetch response, and await the result.
And you need to make your function async and await the promise from the first function.
TotalIncomeData(day, branch_office_id) {
return fetch(...).then(rawResponse => rawResponse.json())
^^^^^^
},
async getTotalIncomes(day, branch_office_id) {
^^^^^
console.log(await this.TotalIncomeData(day, branch_office_id))
^^^^^
},

How to execute the function after the api call is completed in vue js?

i am new to vue js , i have a situation where i have to execute the function getUserViews() after the getUser api call is completed. but looks like the getUserViews is executing before the api call is fully completed.
async initUserLogin() {
await this.getAccountNumber();
if (!this.userHasDetails) {
this.getUser();
}
},
mounted() {
this.$store.commit(types.user.setLogIn);
this.watchBreakpoints();
this.getUserViews();
if (this.loginUser) {
this.initUserLogin();
}
},
You have to add await before this.getUser() (if this returns a promise)
Try also adding the get function after the async call. Then use .then(), this will be called when the request succeeded.
more info about async/await handling can be found here
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
async initUserLogin() {
await this.getAccountNumber();
if (!this.userHasDetails) {
await this.getUser(); //if this returns a promise
}
},
mounted() {
this.$store.commit(types.user.setLogIn);
this.watchBreakpoints();
if (this.loginUser) {
this.initUserLogin().then((response) => {
this.getUserViews();
})
}
}

Debounce Vuex Action Call to Database Not Working

I have a few components that can be separate or on the same page. Each of these components uses the same Vuex state. Since they can each be used on other pages and still work, each of them dispatches a call to the same Vuex action which in turns calls a service that uses axios to get the JSON data.
All of this works great!
However, when I do have 2 (or more) of these components on a single page, that axios call gets called 1 time for each of the components. Initially, I went down the path of trying to see if data existed and get created a "last got data at" timestamp so I could just bypass the 2nd call. However, these are happening both on the components created event and are being essentially called at the same time.
So, enter debounce. Seems like the exact reason for this. However, when I implement it, it fails and is passing on to the next line of code and not awaiting. What am I doing wrong?
Agenda Component (one that uses the same state)
async created() {
await this.gatherCalendarData();
},
methods: {
async gatherCalendarData() {
await this.$store.dispatch('time/dateSelected', this.$store.state.time.selectedDate);
},
},
Month Component (another, notice they are the same)
async created() {
await this.gatherCalendarData();
},
methods: {
async gatherCalendarData() {
await this.$store.dispatch('time/dateSelected', this.$store.state.time.selectedDate);
},
},
The Action getting called
async dateSelected(context, data) {
let result = await getCalendarData(isBetween.date, context.rootState.userId);
await context.commit('SET_MONTHLY_DATA', { result: result.Result, basedOn: isBetween.date });
},
This getCalendarData method is in a service file I created to make api calls (below.)
This is the error that I receive (once for each component) that calls this action.
[Vue warn]: Error in created hook (Promise/async): "TypeError: Cannot read property 'Result' of undefined"
Which is referring to the 3rd line above: result: result.Result
API Service
const getCalendarData = debounce(async (givenDate, userId) => {
let response = await getCalendarDataDebounced(givenDate, userId);
return response;
}, 100);
const getCalendarDataDebounced = async (givenDate, userId) => {
let result = await axiosGet('/api/v2/ProjectTime/BuildAndFillCalendarSQL', {
givenDate: givenDate,
userID: userId,
});
return result;
};
Axios Wrapper
const axiosGet = async (fullUrl, params) => {
let result = null;
try {
let response = await axios.get(fullUrl, params ? { params: params } : null);
result = await response.data;
} catch(error) {
console.error('error:', error);
}
return result;
};
If I put console.log messages before, after and inside the getCalendarData call as well as in the getCaledarDataDebounced methods: (assuming just 2 components on the page) the 2 before logs show up and then the 2 after logs appear. Next the error mentioned above for each of the 2 components, then a single 'inside the getCalendarData' is logged and finally the log from within the debounced version where it actually gets the data.
So it seems like the debouncing is working in that it is only run a single time. But it appears that await call let result = await getCalendarData(isBetween.date, context.rootState.userId); is not truly Waiting.
Am I missing something here?
EDITS after Answer
Based on #JakeHamTexas' answer, my action of dateSelected is now (actual full code, nothing removed like above as to not confuse anything):
async dateSelected(context, data) {
console.log('dateSelected action');
let isBetween = isDateWithinCurrentMonth(data, context.state);
if (!isBetween.result) {
// The date selected is in a different month, so grab that months data
return new Promise(resolve => {
getCalendarData(isBetween.date, context.rootState.userId)
.then(result => {
console.log('inside promise');
context.commit('SET_MONTHLY_DATA', { result: result.Result, basedOn: isBetween.date });
context.commit('SET_SELECTED_DATE', isBetween.date);
context.commit('statistics/TIME_ENTRIES_ALTERED', true, { root: true });
resolve();
});
});
} else {
// The date selected is within the given month, so simply select it
context.commit('SET_SELECTED_DATE', data);
}
context.commit('CLEAR_SELECTED_TIME_ENTRY_ID');
},
And my API call of getCalendarData is now:
const getCalendarData = async (givenDate, userId) => {
console.log('getting calendar data');
let result = await axiosGet('/api/v2/ProjectTime/BuildAndFillCalendarSQL', {
givenDate: givenDate,
userID: userId,
});
return result;
};
The error is gone! However, it does not seem to be debouncing - meaning everything gets called 3 times. I would expect the dateSelected action to be called 3 times. But I would like to avoid the getting calendar data being called 3 times. If it helps, this is what the console looks like:
dateSelected action
getting calendar data
dateSelected action
getting calendar data
dateSelected action
getting calendar data
inside promise
inside promise
inside promise
You need to return a promise from your action. Returning a promise of undefined (which is what is currently happening) resolves immediately.
dateSelected(context, data) {
return new Promise(resolve => {
getCalendarData(isBetween.date, context.rootState.userId)
.then(result => {
context.commit('SET_MONTHLY_DATA', { result: result.Result, basedOn: isBetween.date });
resolve();
}
}
},
Additionally, a vuex commit does not return a promise, so it doesn't make sense to await it.

express fetch promise will not resolve before render

I have an express route and I want to send back the result of a fetch to my pug template. I know my fetch URL works as I have checked it with postman and the data comes back as it should. I would like to store the fetch of the result to the variable called weather at the bottom of the route. My template looks for this variable to exist before adding weather to the template
I have also logged my form data to make sure the form is sending the data to my express server
I get this error in my command console when logging the return:
Promise { <pending> }
(node:18060) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'json' of undefined
I think the issue must be with my promise structure or perhaps it has to do with CORS not being enabled in my app? I'm not getting any errors and I'm hoping someone might have an answer for me??
router.post("/", async(req, res, next)=>{
console.log(req.body.selectedCity)
console.log(req.body.selectedState)
console.log(req.body.selectedZip)
var result = await fetch(`http://api.openweathermap.org/data/2.5/weather?q=${req.body.selectedCity}&units=imperial&appid=${apiKey}`)
.then(function(result) {
console.log(result.json())
})
.then((result)=>{
console.log(result.json())
res.render('index', {states:[
{
id:"none",
name:"choose"
},
{
id:"OH",
name:"Ohio"
},
{
id:"UT",
name:"Utah"
},
{
id:"VT",
name:"Vermont"
},
{
id:"VA",
name:"Virginia"
},
{
id:"WA",
name:"Washington"
},
{
id:"WV",
name:"West Virginia"
},
{
id:"WI",
name:"Wisconsin"
},
{
id:"WY",
name:"Wyoming"
}
],weather:result})
})
});
You have an uncorrect syntax on async/await.
You do not use .then in async/await but you just await the promise and store the result in a variable.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
var result = await fetch(`http://api.openweathermap.org/data/2.5/weather?q=${req.body.selectedCity}&units=imperial&appid=${apiKey}`)
.then(function(result) {
console.log(result.json())
})
.then((result)=>{
console.log(result.json())
res.render [...]
Becomes:
const result = await fetch(`http://api.openweathermap.org/data/2.5/weather?q=${req.body.selectedCity}&units=imperial&appid=${apiKey}`);
console.log(result.json())
res.render [...]
Try and avoid var as it may lead to unexpected behavior.
Try using axios as a fetch library, it's much cleaner than fetch.
https://www.npmjs.com/package/axios
This way it's just const result = await axios.get([...]
This should be structured this way instead -
fetch('url')
.then(result=>result.json)
.then(result=>res.render())
You should also remove async keyword from the callback function provide to router.post.

Execute custom functions one after another - Callback logic in Vue.js

There is a form which submits some data to an API in my component. Assume that it's method is ProcessLogin(). Inside this function I have written my API calls using axios. With the help of then() I have handled my server response and displayed my toast. All good.
Now as a part of my code clean up, I have decided to move all my axios functions to another api.js file and export functions from there. Here is an example function I have in my api.js file :
function ApiLogin(data) {
const url = `${BASE_URL}/authenticate`;
axios.post(url,data).then(response => {
return response;
}).catch(error => {
return error.response;
});
}
On the other side in my component I have my method defined as below :
methods: {
ProcessLogin() {
var status = ApiLogin(this.data);
console.log(status);
}
}
When executing this, I get undefined on my console. I know why it is happening. Because console.log(status) executes before ApiLogin could process and sends it's response. How to handle this kind of situation.? I know that callback is the rescue here, but I am not really sure about how to integrate it.
If you return the axios call from your ApiLogin function:
function ApiLogin(data) {
const url = `${BASE_URL}/authenticate`
return axios.post(url, data)
}
You could then handle the response in your component using then and console log from there:
methods: {
ProcessLogin() {
ApiLogin(this.data)
.then(res => console.log(res))
.catch(err => console.log(err))
}
}
...or with async/await:
methods: {
ProcessLogin: async function() {
try {
var status = await ApiLogin(this.data)
console.log(status)
}
catch(err) {
console.log(err)
}
}
}