ghettovoice / vuelayers

Web map Vue components with the power of OpenLayers
https://vuelayers.github.io/
MIT License
682 stars 230 forks source link

VueLayer invokes emit with context of Vue #468

Closed scadergit closed 2 years ago

scadergit commented 2 years ago

I finally got a chance to get back to bumping our project to VL0.12, and we had an issue due to an override on the Vue emit function. The override merely attempts to log what was emitted and then invokes the original Vue emit funciton.

const emit = Vue.prototype.$emit;
Vue.prototype.$emit = function (...args) {
    if (args.length > 1) {
      console.log(`Event "${args[0]}" from ${this.$vnode.tag}: `, ...args.slice(1) );
    } else {
      console.log(`Event "${args[0]}" from ${this.$vnode.tag}`);
    }
    emit.apply(this, args);
};

The console log may throw an error because the tag property didn't exist on the context of this. VueLayers 0.11 only ever emitted with the context of this as a VueComponent, but in 0.12 that can now also be a Vue, and that naturally wouldn't have the tag property. See screensots below for each, where I added some logging to determine the context of this.

My question is does 0.12 emit using the wrong context of this, or was 0.12 intentionally designed to additonally emit with the context of this as a Vue? I created a sandbox to demonstrate, but having trouble with it importing vuelayers (for some odd reason).

Here is the console output for 0.11: image

Here is the console output for 0.12 (note the "EMIT Vue (no VNode)" lines): image

scadergit commented 2 years ago

...also, and this might relate to #461, but notice the logs where the args passed to emit are "error" and "CancelledError"? Here are those more verbose. If I can get the sandbox running, you can see the error there as well. I would assume something is going wrong, and it should not emit this under normal circumstances? image

ghettovoice commented 2 years ago

Hello @scadergit ,

  1. emit in v0.12: In v0.12.x I'm using an instance of Vue as internal event bus to broadcast lifecycle events between components. This event bus instance is not mounted because it is never mounted. So it is expected that lifecycle event is logged double times, on on the VueLayers component itself and one on the shared event bus. https://github.com/ghettovoice/vuelayers/blob/master/src/mixins/ol-cmp.js#L678

  2. emitting of CanceledError It is here to cancel other lifecycle promises of the current component. Internal building and mounting of OpenLayers instance inside the component is executing asynchronously. So there can be a situation when VueLayers component mounted and then immediately unmounted. And now we need to somehow stop mounting process, i.e. reject mounting promises. Event error with CanceledError arg is used for this purpose.

And it is actually expected to sometimes see this error event, it says that some of the components was rejected to mount. VueLayers by default provides default VlView inside the VlMap if you don't provide it yourself. If you do, then the default VlView (it has id vl-%uuid_of_map%-default-view) mounting is rejecting. So you see a error event with CanceledError instance.

  1. finally about #461 All of the above is expected behaviour. What is unexpected for me: seems that sometimes CanceledError is not catched inside the lib. In the normal circumstances you shouldn't see error log: Uncaught in Promise ... CanceledError. Some time ago I remember that I resolved similar issue... At the current state ofmaster` I can't reproduce it, probably because I using a simple testing app. Maybe you have some additional startup logic in your app, maybe something else, I don't know. I guess there is something like race condition issue
scadergit commented 2 years ago

Thanks for the detailed information. We'll update the function to expect the event bus and errors for that purpose.

I don't believe I'm seeing #461 errors continue; if I do I'll update that issue.