Do something after $emit has finished (successful)

Is it possible to for the $emit event to send a callback back to the child it was emitted from?

Something along the lines off:

methods: {
  test: function () {
    // do something....
    this.$emit('foo', bar, function (callback) {
      if (callback) {
        // do success thing
      } else {
        // do error thing
      }
    })
  }
}

My issues seems to revolve around asynchronous data manipulation, such that the events that take place after the emit depends on the emit being completed. I can’t seem to figure out how to work around this issue other than possibly adding another variable to the parent, propping it down to the child and then watching for changes to that variable and then do stuff based on that result.
See below for current state:

methods: {
  test: function () {
    // do something....
    this.$emit('foo', bar)
    // do something else based on the result of the emit
  }
}

I think the proper vue way would be to emit an event and then watch a prop value to determine when the parent code has run. However I have occasionally found it a lot simpler to just pass a callback method as one of the event arguments:

this.$emit('foo', { bar, done : () => { } });
1 Like

On second thoughts, you can pass multiple parameters to emit so your first example should work?

this.$on('foo', (foo, done) => {});

does that not have the expected result?

1 Like

Turns out it does I was: ‘return done(true)’ the callback instead of setting it as: done(true), it works perfectly now.
Thank you @jackmellis for clarifying it!

In case anyone comes looking here, I ended up doing:

// vue component
export default {
  methods: {
    emit (eventName, value) {
      return new Promise((resolve, reject) => {
        this.$emit(eventName, value)
        this.$nextTick(resolve)
      })
    },
  }
}

This allows you to await your emit event this in your other methods. Eg:

  async emitAndAlert (newVal) {
    await this.emit('value-changed', newVal)
    alert(`value changed to ${newVal}`)
  },
4 Likes

Thanks so much for coming back to this question, I had the exact same issue and your snippet worked perfectly!

1 Like

@Jackson3195 Can you mark @jackmellis answer as the solution if it helped thanks :slight_smile:

I could not make the emit asynchronous but was able to find a work-around for this scenario by passing the parent function as a prop to the child and executing this in an async function of child with await before the call. So the logic is that before deciding which version to execute i.e. synchronous (using emit) or asynchronous (using the prop), it checks if the listener for the emit exists. If it does, it executes the emit version else it executes the prop version. So in the component’s template, you just need to pass either the prop or the listener and the magic will happen!

1 Like
this.$emit('input', someValue)

this.$nextTick(() => {
     // will run after $emit is done
    doSomething()
})
1 Like