Should we unsubscribe from event listeners for 'ready', 'click', etc... in azure-maps-control

MaxEric 40 Reputation points
2024-03-27T16:25:39.75+00:00

Hello Dear All,

I found a lot of examples how to deal with events we subscribed to listen to in Azure Maps event (azure-maps-control), like

map.events.add('mouseover', cluster, markerHovered);
map.events.add('mouseleave', cluster, mouseLeave);
map.events.add('click', cluster, clusterClicked);

So I have a few questions about that:

  1. Should I unsubscribe or doing map.dispose() resolves that internally?
  2. Should check somehow if there's already the same event listener and shouldn't create a new one?

Non of examples tells I should remove those event listeners or check if any similar exists...

I'm using that in ReactJS, so I do map.dispose() when component unmounts.

Tried to ask GPT, it says I should unsubscribe :) But I still don't believe it :)

Azure Maps
Azure Maps
An Azure service that provides geospatial APIs to add maps, spatial analytics, and mobility solutions to apps.
587 questions
0 comments No comments
{count} votes

Accepted answer
  1. rbrundritt 15,231 Reputation points Microsoft Employee
    2024-03-27T18:58:34.5466667+00:00

    Most of the events in Azure Maps are not DOM events and don't need to be removed before disposing the map. The events in Azure Maps are basically a lookup table that is cross referenced when the map feels it needs to raise an event. To free up memory, be sure to set your map object to null or undefined after disposing it, and this will cause the garbage collector in the browser to remove that lookup table. For example:

    map.dispose();
    map = null;
    

    The map makes use of the browsers resize and mouse/touch events, but those are removed automatically when you dispose the map.

    Controls, Markers, and Popups are DOM elements and may have DOM events (e.g. the close button of a popup). When you dispose the map, all controls, popups, markers, and layers are removed from the map automatically, with their events removed too.

    The ability to remove events is there as it is needed for more advanced scenarios, for example the drawing tools module needs to be able to monitor the mouse movement when you are drawing, but once done, that event can be removed. Also, if you plan on reusing the map instance for different scenarios, then you may find adding/removing events is needed.

    So, in summary:

    • Disposing the map => good
    • Disposing the map, then setting the map property to null/undefined => better

    As for the question on checking if an event exists, before creating a new one. If you can reuse an event handler that could make things easier for development and clarity (e.g. future dev needs to know order of operations of logic code for events. They look at code and need to figure out which event handler got called first. If there is only one handler, they only have to look at the logic in there to see the order of operations. Ideally in your code you would know when events are added, and when they need to be removed, and not need to check if an event is already added. In most cases you would only add the ready event once and all other events would be added in that ready event handler. The ready event handler only gets called once, when the map is ready. If you add the event later in the map lifecycle (it's already been ready for a while), the event handler will be called right away once and never called again (useful when creating extensions to Azure Maps and you don't know if the map is ready or not). If you really need to

    While testing all this I did find a couple of events that don't get removed internally when the map is disposed. Most notably the events that power the pinch to zoom behavior. I'll log that issue with the maps team. The following code removes those events map.userInteractionDelegate.pinchZoom.disable(), but this is an undocumented part of the SDK, so best for the maps team to call this line from the dispose method internally.

    If you want to really make sure there are no DOM events left, the following code is a brute force approach.

    function removeAllEvents(element){
    	var events = getEventListeners(element);
    	
    	Object.keys(events).forEach(key => {
    		events[key].forEach(evt => {
    			element.removeEventListener(key, evt.listener);
    		});
    	});
    }
    
    removeAllEvents(map.getCanvas());
    removeAllEvents(map.getCanvasContainer());
    removeAllEvents(map.getMapContainer());
    
    2 people found this answer helpful.

0 additional answers

Sort by: Most helpful