Axios then function also does catch? - vue.js

My post is successful, but I can't do anything in the then statement except console.log(); it always jumps to the catch.
axios.post('/group/15/discussion/'+ this.discussion.id+ '/schedule',this.form, {handleErrors:true})
.then(function(response) {
//this.form.valid = true;
console.log("success");
console.log('set form valid');
this.$refs['schedule-group-discussion-'+this.id].hide();
console.log('close modal');
/*this.$emit('updateDiscussion',response.data.discussion);
this.$toast.success(response.data.message,'Success!',{icon: 'fas fa-check-circle'});*/
})
.catch((error) => {
console.log("catch");
this.form.valid = false;
});
here is my console log in order:
success
set form valid
catch
What is wrong?

The problem is your scope of this. You're actually getting an error, cannot read property valid of undefined, but you didn't console.log(error). You need to use the fat arrow function in your .then() as well:
.then(function(response) {
to
.then((response) => {
Now this is scoped correctly.

Related

How to use the functions for list filtering

I am struggling to learn implementing api in vue and filter the data but I can’t make it work.
This is code sandbox I created:
https://codesandbox.io/embed/agitated-architecture-91tj6?file=/src/components/HelloWorld.vue:943-971&codemirror=1
I am able to print the data but not to filter them even though I am using function for it.
If anyone can lead me in right path I would appreciate.
I saw your sandbox, here is how to make your code work:
methods: {
onChange() {
axios
.get("https://api.github.com/users")
.then((response) => {
this.results = response.data;
this.filterResults();
this.modal = true;
})
.catch((error) => {
console.log(error);
this.errors = true;
})
.finally(() => console.log("Data successfully loaded"));
},
filterResults() {
this.filteredResults = this.results.filter((result) => {
return result.login.toLowerCase().includes(this.search.toLowerCase());
});
},
.............
Explanation:
In your code, you write:
onChange() {
axios
.get("https://api.github.com/users")
.then((response) => {
this.filteredResults = response.data;
})
.catch((error) => {
console.log(error);
this.errors = true;
})
.finally(() => console.log("Data successfully loaded"));
this.filterResults();
this.modal = true;
},
You can see the position of this.filterResults(); is wrong. That is because you put the method outside of axios or calling api. The axios is asynchronous function, it means that it will wait for the data to be loaded, while method this.filterResults(); don't need to wait. This means that the method this.filterResults(); will be loaded before the axios function finished even if you put it in the order below the axios function, basically it means that you are calling this.filterResults(); function when the data is still empty. The solution to this is that by calling this.filterResults(); inside the axios function, you can put it in .then() if you want to use the successfully retrieved data.
The second problem in your code is in the filtering logic.
filterResults() {
this.filteredResults = this.results.filter((result) => {
return result.toLowerCase().includes(this.search.toLowerCase()) > -1;
});
},
From what I understand, you want to filter the result with the this.search data from the input. Here you are calling this.results, but when do you assign any value to the this.resuts? in the axios you assign the value to this.filteredResults = response.data; instead of this.results= response.data;, it means the variable this.results is empty. So you have to change this.filteredResults = response.data; to this.results = response.data; in axios.
Next is the logic in your filter
return result.toLowerCase().includes(this.search.toLowerCase()) > -1;
What you want to achieve is filtering the result.login with this.search value. But here you are filtering the result which as object type data with this.search value. Also, you don't need to put > -1 operation, because includes will return true or false.

Vuex action "not a function" inside Nuxt fetch

I have just introduced error handling to one of my Nuxt pages and apparently the action mapped and called inside fetch raises a not a function error. If the try/catch block isn't there it works as expected and there's no error at all.
Here is my component stripped to the essential parts:
export default {
name: 'ViewArticle',
async fetch ({ error }) {
try {
await this.fetchArticle({ articleSlug: this.articleSlug })
} catch (err) {
error({ statusCode: 404, message: 'May the force be with you' })
}
},
computed: {
...mapGetters({
article: 'article/single'
}),
articleSlug () {
return this.$route.params.articleSlug
}
},
methods: {
...mapActions({
fetchArticle: 'article/fetchOne'
})
}
}
I am assuming that somehow mapActions only gets executed later in the spiel, but can't figure out how to prevent the error. This way, basically every time I load the page it gets immediately redirected to the error page.
The error message I'm getting is the following. Obviously fetchArticle is a function, and unless it's inside the try/catch block, it works as expected.
this.fetchArticle is not a function 03:30:51
at Object.fetch (52.js:32:18)
at server.js:2881:39
at Array.map (<anonymous>)
at module.exports../.nuxt/server.js.__webpack_exports__.default (server.js:2864:51)
Fetch provides the context as argument.
fetch(context)
Inside the context we can find our store. Here you can take a look what context contains: https://nuxtjs.org/api/context
fetch(context) {
let store = context.store;
}
People like to destructure it
fetch({ store }) {}
Your code should look like this:
async fetch ({ error, store }) {
try {
await store.dispatch('article/fetchOne', { articleSlug: this.articleSlug })
} catch (err) {
error({ statusCode: 404, message: 'May the force be with you' })
}
},
Fetch gets executed on the server side, thats why you get is not an function error. Its undefined
... fetch is called on server-side...
Use async fetch({store})
async fetch ({ error, store }) {
try {
await store.dispatch( 'article/fetchOne' , { articleSlug: this.articleSlug })
} catch (err) {
error({ statusCode: 404, message: 'May the force be with you' })
}

Error handling in Vue JS - errors not caught

I have the following code:
fooService.update(this.bar).then( this.$emit('updated', this.updatedBar),).catch(err => {...
If an error is encountered, then the error is not caught. If I change the code to be:
fooService.update(this.bar).then(x => {this.$emit('updated', this.updatedBar);}).catch(err => {...
Then the error is caught and shows as expected. Can anyone explain to me what is going on and why it behaves in that way?
Edit
Underlying service code:
function updateBar(bar) {
return $http.put(`/api/bar/${bar.Id}`, bar);
}
So I still think the error is happening in the this.$emit the reason why, in
fooService.update(this.bar).then( this.$emit('updated', this.updatedBar),).catch(err => {
It has to evaluate the this.$emit first as you're setting the response from that function as the .then and not the call itself.
Proof of it doing that
function emit(){
console.log('emit')
}
var promise = new Promise(function(resolve,reject){
setTimeout(() => {
console.log('promise is done')
reject();
}, 1000)
})
promise.then(emit()).catch( function() {console.log('carry on');})
notice how it logs "emit" first
Now if that errors you can see it doesn't hit the catch
function emit(){
console.log('emit')
throw new Error("bad")
}
var promise = new Promise(function(resolve,reject){
setTimeout(() => {
console.log('promise is done')
reject();
}, 1000)
})
promise.then(emit()).catch( function() {console.log('carry on');})
So under the hood it's doing this (the simplest way I can think of)
emit()
try{
getService()
} catch{
...
}
Whereas if you actually pass the .then a function it changes the order of things
function emit(){
console.log('emit')
throw new Error("bad")
}
var promise = new Promise(function(resolve,reject){
setTimeout(() => {
console.log('promise is done')
reject();
}, 1000)
})
promise.then(() => {emit()}).catch( function() {console.log('carry on');})
and again under the hood it looks like this
try{
getService()
emit()
} catch{
...
}

RxJS HTTP request error handling

In my project, I use RxJS to handle HTTP request. I came into a confusing point about the error handling part as following:
.switchMap((evt: any) => {
return http.getComments(evt.params)
.map(data => ({ loading: false, data }))
.catch(() => {
console.log('debugging here');
return Observable.empty();
});
})
in the above code, inside the switchMap operator, I use the http.getComments function to send request, which is defined by myself as following:
getComments(params) {
return Observable.fromPromise(
this.io.get(path, { params })
);
}
in this function, I use fromPromise operator convert the returned Promise to observable.
The problem is when HTTP request failed, the catch operator inside switchMap can not work, the debugging console can't output. So what's wrong with my code.
Do you really need to catch the error inside the switchMap anyway? You can handle your error in your source if you want.
.switchMap((evt: any) =>
http.getComments(evt.params).map(data => ({ loading: false, data }))
})
.subscribe(console.log, console.error);
Any way, your source code does not look to have any error, maybe your promise is not been rejected when the http fails and is just resolving with an error as a response (this is a guess because I've seen that before)
Your code should work. Here a simplified simulation, where http calls are substituted by a function which raises an error.
import {Observable} from 'rxjs';
function getComments(params) {
return Observable.throw(params);
}
const params = 'abc';
Observable.of(null)
.switchMap(_ => {
return getComments(params)
.map(data => ({ loading: false, data }))
.catch(err => {
console.log('debugging here', err);
return Observable.empty();
});
})
.subscribe(
console.log,
error => console.error('This method is not called since the error is already caught', error),
() => console.log('DONE')
)

How Can I pass params with an API client to vue-head?

I am passing params from my API to vue-head but every time I do that it send me undefined in the head this is the code:
export default {
data: () => ({
errors: [],
programs: [],
}),
methods: {
getProgram() {
this.api.http.get(`videos/program/${this.programSlug}`)
.then(response => {
this.programs = response.data
})
.catch(error => {
this.errors = error
});
}
},
head: {
title: function() {
return {
inner: this.programs.name,
separator: '|',
complement: 'Canal 10'
};
}
}
}
any idea what I am doing wrong with my code??
First verify you are fetching the information correctly. Use console log and go to network tab and verify you are fetching the data correct, you might have to comment out vue-head. But what I think is that the problem might be due to vue-head rendering before the api call finishes then no data is being passed.
If you are using vue-router this can be easily solved with beforeRouteEnter() hook. But if not! apparently vue-head has an event that you can emit to update the component after render.
I haven't tried this but it should work. you can add the function below to your methods and call it after the promise is resolved i.e in the then closure.
methods: {
getProgram() {
this.api.http.get(`videos/program/${this.programSlug}`)
.then(response => {
this.programs = response.data
this.$emit('updateHead')
})
.catch(error => {
this.errors = error
});
}
}