[Vuejs]-Vue reactive data showing as Observer and not actual value

3👍

Returning Promises from Vue’s lifecycle hooks doesn’t do much. It certainly doesn’t make them wait for the Promise to complete. The same would be true using async/await.

Internally the hooks are called using callHook, e.g. callHook(vm, 'mounted'). You can see the code for callHook at:

https://github.com/vuejs/vue/blob/b7c2d9366cf731a1551286b8ac712e6e0905070e/src/core/instance/lifecycle.js#L336

This calls out to invokeWithErrorHandling, which you can see at:

https://github.com/vuejs/vue/blob/b7c2d9366cf731a1551286b8ac712e6e0905070e/src/core/util/error.js#L36

While invokeWithErrorHandling does have some minimal support for handling any Promises that are returned, those Promises are ignored by callHook.

In the code shown in the question the created hook will be called followed by the mounted hook. The then on the getConversation Promise won’t be called until later as that will be asynchronous.

So at the point mounted is called the value of this.conversation will still be its initial value, presumably an empty object. Vue’s reactivity system will cause that to be shown as {__ob__: Observer} in the console.

If the component needs that data to be able to function then the parent will have to take responsibility for loading that data and delay creating the component until the data is available.

More likely the component will just need to cope with the data being missing when it’s first rendered. It will then need to chain together the asynchronous calls using Promises:

created() {
  this.getConversation(this.$route.params.ConversationId).then(
    respConversation => {
      this.conversation = respConversation;
      this.getConversationTranscripts(this.conversation.AudioId);
    }
  );
}

Using async/await is maybe a little cleaner here:

async created() {
  this.conversation = await this.getConversation(this.$route.params.ConversationId)
  this.getConversationTranscripts(this.conversation.AudioId);
}

None of this will pause the component’s lifecycle, so rendering will continue with this.conversation still set to its initial value and the template will have to be coded to deal with that.

I would add that using this.$route.params.ConversationId is not ideal. If possible this would be injected via a prop instead. You’ll also need to be very careful when this value changes. If the value changing causes a new component to be created then no problem but if it just updates the existing component you could run into problems. The created and mounted hooks only run once, when the component is first created, so reusing the same component when the params change won’t run them again.

Leave a comment