admin管理员组文章数量:1336645
I am using
"axios": "^0.19.0",
"vue": "^2.6.10",
"vuex": "^3.1.1"
My vuex
action looks like this and calls a remote interface using axios
. The request does work and it receives a valid response.
skipQuestion({mit}, payload) {
let params = {
answer: {
id: payload.id,
skipped: true,
}
};
return new Promise((resolve, reject) => {
mit(UPDATE_LOADING, true);
Remote.put(`/answer.json`, params)
.then((response) => {
mit(UPDATE_LOADING, false);
mit(SKIP_QUESTION, payload.id);
resolve();
})
.catch((error) => {
mit(UPDATE_LOADING, false);
reject(error);
})
})
},
The ponent Question
does have the following method skip
, which calls the vuex
action skipQuestion
and should emit the skip
event to the parent ponent.
...mapActions(['skipQuestion']),
skip(evt) {
let payload = { id: this.question_id };
this.skipQuestion(payload).then( () => {
this.$emit('skip', this.uuid);
}).catch( (error) => {
console.log(error);
});
},
The problem is, that the skip
event is not emitted to the parent when using it within the then
block of the action. The vue developer console for chrome also confirms, that the skip
event was fired. If I put the emit outside the block, everything works. Any suggestions whats going wrong?
Edit 1
Also tried the following code and both log statements are printed to the console.
skip(evt) {
let payload = { id: this.question_id };
let vm = this;
this.skipQuestion(payload).then( () => {
console.log('before skip emit');
vm.$emit('skip', this.uuid);
console.log('after skip emit');
}).catch( (error) => {
console.log(error);
});
},
Edit 2
Here is the template code which is used to listen to the child events:
<question v-bind="question"
:key="question.uuid"
v-if="questionReady"
v-on:skip="onSkipQuestion"
v-on:answer="onAnswerQuestion">
</question>
As told before, if not using the Promise/then-block returned by the axios
request, the emit does work. Below you'll find the method which should be called:
methods: {
onSkipQuestion(payload) {
// this code is not executed
console.log('onSkipQuestion')
//....
},
//....
}
I am using
"axios": "^0.19.0",
"vue": "^2.6.10",
"vuex": "^3.1.1"
My vuex
action looks like this and calls a remote interface using axios
. The request does work and it receives a valid response.
skipQuestion({mit}, payload) {
let params = {
answer: {
id: payload.id,
skipped: true,
}
};
return new Promise((resolve, reject) => {
mit(UPDATE_LOADING, true);
Remote.put(`/answer.json`, params)
.then((response) => {
mit(UPDATE_LOADING, false);
mit(SKIP_QUESTION, payload.id);
resolve();
})
.catch((error) => {
mit(UPDATE_LOADING, false);
reject(error);
})
})
},
The ponent Question
does have the following method skip
, which calls the vuex
action skipQuestion
and should emit the skip
event to the parent ponent.
...mapActions(['skipQuestion']),
skip(evt) {
let payload = { id: this.question_id };
this.skipQuestion(payload).then( () => {
this.$emit('skip', this.uuid);
}).catch( (error) => {
console.log(error);
});
},
The problem is, that the skip
event is not emitted to the parent when using it within the then
block of the action. The vue developer console for chrome also confirms, that the skip
event was fired. If I put the emit outside the block, everything works. Any suggestions whats going wrong?
Edit 1
Also tried the following code and both log statements are printed to the console.
skip(evt) {
let payload = { id: this.question_id };
let vm = this;
this.skipQuestion(payload).then( () => {
console.log('before skip emit');
vm.$emit('skip', this.uuid);
console.log('after skip emit');
}).catch( (error) => {
console.log(error);
});
},
Edit 2
Here is the template code which is used to listen to the child events:
<question v-bind="question"
:key="question.uuid"
v-if="questionReady"
v-on:skip="onSkipQuestion"
v-on:answer="onAnswerQuestion">
</question>
As told before, if not using the Promise/then-block returned by the axios
request, the emit does work. Below you'll find the method which should be called:
methods: {
onSkipQuestion(payload) {
// this code is not executed
console.log('onSkipQuestion')
//....
},
//....
}
Share
edited Oct 23, 2019 at 7:47
anka
asked Oct 18, 2019 at 11:14
ankaanka
3,8571 gold badge31 silver badges38 bronze badges
5
- 1 Maybe not the definitive solution to your problem, but you should definitely try switching to await / async instead of using raw promises – coyotte508 Commented Oct 18, 2019 at 11:17
-
I'm assuming that you have on your parent ponent something like
v-on:skip=somfunc
to listen to theskip
event. is that right? – Carlos Crespo Commented Oct 22, 2019 at 9:46 -
Yes of course, I also tried
@skip=somefunc
. As mentioned if I emit it outside thethen
block everything works fine. – anka Commented Oct 22, 2019 at 13:18 - Can you add your template code ? – Pierre Burton Commented Oct 22, 2019 at 14:27
-
Maybe try to use
.bind()
for this method, then maybe your parent mponent will also see this event. Or maybe try to makeskip
arrow function insidedata() {return { skip: () => ....}}
– Krzysztof Kaczyński Commented Oct 26, 2019 at 9:46
4 Answers
Reset to default 4Summarize your information given:
The vue developer console for chrome also confirms, that the skip event was fired.
TL;DR
vm.$emit
bassically calls every method listed invm._events[eventName]
v-on
gets registered viacontext.listeners
increateElemet
and injected viaupdateListeners
Basically you can debug using debugger
statement:
skip(evt) {
let payload = { id: this.question_id };
this.skipQuestion(payload).then( () => {
debugger; // scope -> _events & scope -> $parent.ponentInstance
// or console.log(JSON.stringify(this._events))
this.$emit('skip', this.uuid);
}).catch( (error) => {
console.log(error);
});
},
Then you know whats happening.
Things to check:
valid
this
scopevalid
parent
actually triggered as resolved
vm._events
registered
You have lost the reference to this
inside the then block. The reference is now the callback function called. Instead do this
...mapActions(['skipQuestion']),
skip(evt) {
let payload = { id: this.question_id };
let vm = this; // Preserve Vue instance for use inside block
this.skipQuestion(payload).then( () => {
vm.$emit('skip', vm.uuid);
}).catch( (error) => {
console.log(error);
});
},
Maybe the problem is that you don't return resolve() or reject() in skipQuestion().
Anyway, assuming your application uses ES2017 (or higher), or if not then Babel, I would refine the function to use async / await
structure so that this
would not be at any risk (referring to Varun's answer), and not in any risk if skipQuestion()
doesn't return anything, like as is currently:
async skip(evt) {
let payload = { id: this.question_id };
try {
let result = await skipQuestion(payload)
this.$emit('skip', this.uuid);
} catch(error){
console.log(error);
}
}
Not returning resolve / reject
is a known source of bugs in case of Promise((resolve, reject) => {...})
syntax
I had this exact same problem and could not for the life of me figure out what was going on. All I can think of is that somehow the ponent is losing the ability to emit events while awaiting the promise resolution.
Anyway, my solution was to emit the promise itself, like this:
skip(evt) {
let payload = { id: this.question_id };
this.$emit('skip', skipQuestion(payload));
}
And on the parent, you can do
... @skip="receive_skip($event)" ...
...
methods: {
receive_skip(skipped) {
skipped
.then((data) => {
// do something on success
})
.catch((err) => {
// do something on fail
});
}
}
It's not as clean and elegant, but it gets the job done.
本文标签: javascriptVuejs component does not emit to parent after successful axios callStack Overflow
版权声明:本文标题:javascript - Vue.js component does not emit to parent after successful axios call - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742262125a2442708.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论