In an event handler, one can easily mix property modifications and method calls (which is great), as in:
<span @click=" accumulator += fetchNextItem() ">do it</span>
However, if the called method is async, one need to actually wrap this code in an additional method like:
<span @click=" fetchAndAccumulateNextItem() ">do it </span>
....
methods: {
async fetchAndAccumulateNextItem() {
this.accumulator += await this.fetchNextItem()
},
async fetchNextItem() { .... } /* unmodified */
}
This can be slightly inconvenient if there are many asynchronous methods of which we use the return value.
I think this might become more and more common as people start understanding and using async/await more and more.
Initial context: I have a very specific use case of a vuejs<->python bridge that makes (among other things) all the python-written method callable from vuejs, but as the call goes through websockets, all methods end up async. https://github.com/twitwi/vuejs-python
I'd suggest a ".async" modifier that would allow for "await" in the event handler snippet.
For the example above, it would be written as:
<span @click.async=" accumulator += await fetchNextItem() ">do it</span>
(this is probably useful for all types of events, not only click)
I don't think it's worth adding another modifier that only serves a very few uses cases: there are not many cases where the code is still readable when doing an await inside an event handler in the html. You don't need to create a method, you should be able to do:
<span @click=" async () => accumulator += await fetchNextItem() ">do it</span>
You could also create your own function helpers that are accessible globally like asyncAdd:
<span @click=" asyncAdd(accumulator, fetchNextItem())">do it</span>
which ends up being shorter than the proposal.
Let's wait for more feedback on this
Thanks for the reply.
I like the first workaround, I'd give it a try
:+1:
For some reason, I needed to add some parentheses around it, but it works well.
For the record, I give the result here.
For the example above, this yields:
~vue
do it
~
For my use case (with affecting an attribute), this gives:
~vue
fetch
~
Or, alternatively, inspired by the second suggestion:
~vue
fetch
~
~javascript
methods: {
async asyncSet (attr, asyncVal) {
this.$set(this, attr, await asyncVal)
},
}
~
Thanks again for the workarounds.
@posva it looks like the parser doesn't understand async function expressions. Here's the compiler output:
function render() {
with(this) {
return _c('span', {
on: {
"click": function ($event) {
async () => accumulator += await fetchNextItem()
}
}
}, [_v("do it")])
}
}
async inline function epxression demo
It appears to nest the entire string inside a normal function. Should this issue be re-purposed or create a new one?
I'm guessing the expected output should be:
function render() {
with(this) {
return _c('span', {
on: {
"click": async () => accumulator += await fetchNextItem()
}
}, [_v("do it")])
}
}
@sirlancelot you are right, I adapted the compiler to allow it: https://github.com/vuejs/vue/pull/10361
This works for me:
@input="(async function(){myVariable= await _queryVals($event)})()"
but this failed:
@input="(async ()=>{myVariable= await _queryVals($event)})()"
Syntax Error: SyntaxError: await is a reserved word
It appears I can't use await inside an arrow function inside of an inline event handler.
Most helpful comment
I don't think it's worth adding another modifier that only serves a very few uses cases: there are not many cases where the code is still readable when doing an
awaitinside an event handler in the html. You don't need to create a method, you should be able to do:You could also create your own function helpers that are accessible globally like
asyncAdd:which ends up being shorter than the proposal.
Let's wait for more feedback on this