Raruto / leaflet-elevation

Leaflet plugin that allows to add elevation profiles using d3js
GNU General Public License v3.0
254 stars 82 forks source link

`track_info.distance` is undefined within `"eledata_loaded"` event #241

Closed haldo98 closed 1 year ago

haldo98 commented 1 year ago

Hi...

i have this simple code

controlElevation.on('eledata_loaded', ({track_info}) => {
  console.log(track_info.distance + " km");
});

on my demo page https://www.tadini.it/temp/map.html

it is supposed to log the total distance... but it seems that it is not always working... sometime it logs "undefined" and then after refreshing the page (sometimes I have to refresh it many times) shows the correct number,

Raruto commented 1 year ago

it is supposed to log the total distance... but it seems that it is not always working... sometime it logs "undefined"

If I understand correctly it happens more often on the first load

and then after refreshing the page (sometimes I have to refresh it many times) shows the correct number,

Sometimes it can also be just a problem with a cache (server or browser side).

You should try to trigger an error (or at least debug it step by step) to try to find the cause behind this behavior.

BTW, you could also rewrite your code as follows:

var controlElevation = L.control.elevation(elevation_options).addTo(map);

// controlElevation.load(url); // <-- depending on the download speed of this file it can lead to unexpected behaviors

controlElevation.on('eledata_loaded', ({track_info}) => {
  console.log(track_info.distance + " km");
});

controlElevation.load(url); // <-- load the track after attaching any other event listener that relays on it

👋 Raruto

haldo98 commented 1 year ago

I modified the code as you suggested but the issue is still there. It happens though only with the calculated field (lenght and max elevation for instance) not with the name or the coordinates

Raruto commented 1 year ago

In order to try to find the reason behind all this in your listener try throwing an exception when that value is undefined and then start debugging step by step.

It happens though only with the calculated field (lenght and max elevation for instance) not with the name or the coordinates

Keep in mind that some assets are dynamically loaded ("lazy loaded") if you don't load them first within the page, here are some references:

https://github.com/Raruto/leaflet-elevation/blob/868179234d8e9b8f7beaea57d0e34d8bd79a2622/src/control.js#L19-L29

Just in case, you can simply try to include these files via several <script> tags if you always want to make sure that these assets are always loaded before the "lealfet-elevation" library (NB this also applies to some files in the library itself, eg all those within the src/handlers folder which are responsible for performing all the dynamic calculations you mention above).

👋 Raruto

haldo98 commented 1 year ago

tried everything I can.. (not so much btw.. I'm not an expert) but the issue is still there....

Happens also with your example...

https://raruto.github.io/leaflet-elevation/examples/leaflet-elevation_custom-summary.html

Raruto commented 1 year ago

Hi @haldo98,

I think the only way to try and debug this is to start trying to find out how to make it reproducible.

Take look at the various *.spec.js files I've started adding in here https://github.com/Raruto/leaflet-elevation/pull/246 to get an idea.

Below is a brief explanation on how you can use them:

npm i         # install dependencies
npm run dev   # (optional) start a dev server at: http://localhost:8080
npm run test  # test all the ".*spec.js" files
// SOURCE FILE: examples/leaflet-elevation.spec.js
// TESTED FILE: examples/leaflet-elevation.html

const test = suite('examples/leaflet-elevation.html');

test('eledata_loaded', async ({ page }) => {

  // in this case `const gpx = ` will holds the value returned by `resolve(gpx)`
  const gpx = await page.evaluate(() => new Promise(resolve => {
    // here you can access any variable defined within "examples/leaflet-elevation.html" do get an idea what to expect, eg: `console.log(controlElevation)`
      controlElevation.on('eledata_loaded', (gpx) => resolve(gpx));
  }));

  assert.is(gpx.name, 'via-emilia.gpx');
  assert.not.type(gpx.layer, 'undefined');        // this is your expected assertion
  assert.type(gpx.track_info.distance, 'number');

});

👋 Raruto