Skip to content

Create an ".async" modifier for event handlers #10338

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
twitwi opened this issue Aug 3, 2019 · 6 comments
Open

Create an ".async" modifier for event handlers #10338

twitwi opened this issue Aug 3, 2019 · 6 comments

Comments

@twitwi
Copy link

twitwi commented Aug 3, 2019

What problem does this feature solve?

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

What does the proposed API look like?

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)

@posva
Copy link
Member

posva commented Aug 3, 2019

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

@twitwi
Copy link
Author

twitwi commented Aug 3, 2019

Thanks for the reply.
I like the first workaround, I'd give it a try

@twitwi
Copy link
Author

twitwi commented Aug 3, 2019

👍
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:

<span @click="(async () => accumulator += await fetchNextItem())">do it</span>

For my use case (with affecting an attribute), this gives:

<a @click="(async()=> title = await fetchTitle())">fetch</a>

Or, alternatively, inspired by the second suggestion:

    <a @click="asyncSet('title', fetchTitle())">fetch</a>
    methods: {
        async asyncSet (attr, asyncVal) {
            this.$set(this, attr, await asyncVal)
        },
    }

Thanks again for the workarounds.

@sirlancelot
Copy link

sirlancelot commented Aug 5, 2019

@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")])
  }
}

@posva
Copy link
Member

posva commented Aug 7, 2019

@sirlancelot you are right, I adapted the compiler to allow it: #10361

@adjenks
Copy link

adjenks commented Nov 28, 2019

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants