Calling Promise with Axios in Vue 2 - vue.js

How to implement Promise in this Axios POST request for Vue-Snotify?
This is my Axios post request:
const url = 'https://foobar.api/photos';
axios.post(url, {photo: "data:image/jpeg;base64," + photo})
.then(function (response) {
console.info('Done');
})
.catch(function (error) {
console.error(error);
});
This package Vue-Snotify I want to add as a notifier what will show a notify box with a loader showing the progress. This is what it should look like regarding the docs:
this.$snotify.async('Called with promise', 'Success async', () => new Promise((resolve, reject) => {
setTimeout(() => resolve({
title: 'Success!!!',
body: 'We got an example success!',
config: {
closeOnClick: true
}
}), 2000);
}));
But how to achieve this? I'm no pro in Vue and can't figure out how to combine those two.

You can return axios to accomplish this but if you catch the error Snotify will show a success message. Try this:
this.$snotify.async('Called with promise', 'Success async', () => {
const url = 'https://foobar.api/photos';
return axios.post(url, {photo: "data:image/jpeg;base64," + photo})
.then(function (response) {
console.info('Done');
})
.catch(function (error) {
// handle error first
throw error;
});
}));
EDIT: If you want to control the messages to this instead:
this.$snotify.async('Called with promise', 'Success async', () => {
return new Promise((resolve, reject) => {
const url = 'https://foobar.api/photos';
return axios.post(url, {photo: "data:image/jpeg;base64," + photo})
.then(function (response) {
resolve({
title: 'Success!!!',
body: 'We got an example success!',
config: {
closeOnClick: true
}
})
})
.catch(function (error) {
reject({
title: 'Error!!!',
body: 'We got an example error!',
config: {
closeOnClick: true
}
})
});
});
});
Fiddle:
https://jsfiddle.net/qo6fdv1n/2/

Related

Using Axios to retry request after refreshing JWT token in Vuex store

I'm trying to use Axios to retry failed requests due to JWT expiry
So far I have then following request in a method on a Vue component:
getAPI2.get("/api/v1/sessions/",{ headers: headers }).then(response => {
console.log(response);
this.items = response.data.items;
});
This is using the below interceptor when it hits an error
const getAPI2 = axios.create({
baseURL: '/'
})
getAPI2.interceptors.response.use(response => response, err => {
if (err.config && err.response && err.response.status === 401) {
store.dispatch('refreshToken')
.then(access => {
axios.request({
method: 'get',
headers: { Authorization: `Bearer ${store.state.accessToken}` },
url: err.config.url
}).then(response => {
console.log('Successfully got data')
console.log(response)
return response;
}).catch(err => {
console.log('Got the new access token but errored after')
return Promise.reject(err)
})
})
.catch(err => {
return Promise.reject(err)
})
}
})
I'm seeing the data when the request hits an error and goes through the interceptor but I think there's an issue in passing back the response to my component
Apologies if this is obvious, my javascript knowledge is in its infancy
After some playing around I managed to get this working:
const getAPI3 = axios.create({
baseURL: '/'
})
getAPI3.interceptors.response.use( (response) => {
// Return normal response
return response;
}, (error) => {
// Return non auth error
if (error.response.status !== 401) {
return new Promise((resolve, reject) => {
reject(error);
});
}
return store.dispatch('refreshToken')
.then((token) => {
// Make new request
const config = error.config;
config.headers = { Authorization: `Bearer ${store.state.accessToken}` }
return new Promise((resolve, reject) => {
axios.request(config).then(response => {
resolve(response);
}).catch((error) => {
reject(error);
})
});
})
.catch((error) => {
Promise.reject(error);
});
});

Why is my VueJS Login reloading despite catch being called?

I have the following code. The catch() is getting called, I can see the toastr alert. However immediately after the page reloads. Any idea why?
signIn() {
this.$store
.dispatch('auth/login', this.credentials)
.then(() => {
this.$toastr.s('You are successfully logged in')
this.$router.push({ name: 'About' })
})
.catch(() => {
// this.$toastr.e('You are successfully logged in')
this.$toastr.e('Please check the form')
})
}
Login Code:
login({ commit }, data) {
commit(types.AUTH_ERROR_CHANGE, null)
// console.log(process.env.VUE_APP_API_URL);
const url = process.env.VUE_APP_API_URL + '/authentication_token'
return new Promise((resolve, reject) => {
axios
.post(url, data)
.then(response => {
commit(types.AUTH_UPDATE_TOKEN, response.data)
resolve(state)
})
.catch(() => {
commit(types.AUTH_ERROR_CHANGE, 'Incorrect username or password')
reject(state)
})
})
},``
Sorry all, the problem was elsewhere completely.
I had an axios interceptor from previous code:
axios.interceptors.response.use(
data => {
store.commit('general/' + types.LOADING_STOP)
return data
},
error => {
store.commit('general/' + types.LOADING_STOP)
if (
error.response &&
error.response.status &&
error.response.status === 401
) {
// window.location.href = '/login'
}
return Promise.reject(error)
}
I had an old location.href there

Vuex promise reject returns undefined

I want the promise reject to return the error to my method but the response is empty inside my methods then() function, how can i get the error response to be returned to my method for further use or even inside the catch function.
My vuex action
//authAction
login({ commit }, payload) {
new Promise((resolve, reject) => {
user.login(payload.user.email, payload.user.password)
.then(response => {
const user = response.data.user;
// If there's user data in response
if (user) {
const payload = [user]
commit('AUTH_SUCCESS', payload, { root: true })
resolve(response)
} else {
reject({ message: "Sorry, cant login right now" })
}
})
.catch(error => {
console.log(error.response.status)
reject(error)
})
})
}
My method
// Login method
login() {
if (!this.checkLogin()) return;
this.$vs.loading();
const payload = {
checkbox_remember_me: this.checkbox_remember_me,
user: {
email: this.email,
password: this.password
}
};
this.$store
.dispatch("auth/login", payload)
.then(res => {
this.$vs.loading.close();
console.log(res);
})
.catch(error => {
this.$vs.loading.close();
this.$vs.notify({
title: "Error",
text: error.message,
});
});
}
What am i missing?
Thanks in advance!
My solution is to 1. dispatch an action whenever an error is thrown which updates state 2. watch state change in view and do something with it

How to get Html code by fetching web API response?

When we are trying to fetch html code via fetch API response but we are enable to get it because it return "Unexpected Token <"
onLoginService2 = async () => {
try {
var hittingURl = "https://members.iracing.com/membersite/Login?username=dave#rms55.com.au&password=rms55Pa55&utcoffset=-600&todaysdate=1558055491688&checkbox=0";
const myRequest = new Request(hittingURl.toString(),
{
method: 'POST',
headers: {
'Accept': 'text/html',
'Content-Type': 'text/html;charset=ISO-8859-1',
},
timeout: 1000,
// body: JSON.stringify("")
}
);
fetch(myRequest)
.then((response) => console.log("abcdefghijklmon--> "+JSON.stringify(response)))
.then((data) => {
console.log("RESPONSERR----> ",data+"");
// this.setState({ isLoading: false })
// this.onLoginSuccessFull(responseJson)
})
.catch((error) => {
this.setState({ isLoading: false })
console.log("response--31" + error);
})
} catch{
}
// }
}
The response of first then has a method .text(), which return Promise
Try this
fetch(myRequest)
.then(resp => resp.text())
.then(text => {
//text is html
})
*Just copy the above and run in console to see the result.

Passing an error to a component

I have an AddComment.vue component which has a form, on submit it hits a laravel api endpoint where validation happens. If validation fails I want to show the errors in AddComment.vue. How can return the error.response object to AddComment.vue? Currently, I can see 'fired' in the console when I want to be logging the error. Where am I going wrong any help would be greatly appreciated
AddComponent.vue
methods: {
addComment() {
this.$store.dispatch('addComment', {
name: this.name,
email: this.email,
body: this.body
})
.then(response => {
this.$router.push({ name: 'home' })
console.log('fired')
})
.catch(error => {
console.log(error)
})
},
}
store.js
actions: {
addComment(context, comment) {
new Promise((resolve, reject) => {
axios.post('/comments', {
name: comment.name,
email: comment.email,
body: comment.body,
approved: false
})
.then(response => {
context.commit('addComment', response.data)
resolve(response)
})
.catch(error => {
reject(error)
})
});
},
}
The catch() block only gets called if the Laravel backend throws an error. So if you are returning a normal status code of 2xx then axios always calls the .then() part. In that case, you have to resolve the error message yourself.
Try something like this in your backend route (it will return an error):
return response()->toJson([
'message' => 'error message',
], 500);
And see if this responds with an actual error in you vuejs application.