Esri / esri-leaflet

A lightweight set of tools for working with ArcGIS services in Leaflet. :rocket:
https://developers.arcgis.com/esri-leaflet/
Apache License 2.0
1.61k stars 799 forks source link

Cancel Previous Pending Requests #749

Open bdk0172 opened 8 years ago

bdk0172 commented 8 years ago

We are displaying a customer's ArcGIS tiles within Mapbox and every time zoom is used, requests for tiles are sent out. With this particular customer, not sure if their server is slow or experiencing network issues, but it appears that it gets hung up and all requests are sitting in a pending status when looking at the network tab in Chrome developer tools. Is there anyway possible to cancel previous requests when another zoom is done? It has to wait for all previous requests to return before it displays the tiles for the final zoom level. In some cases this is taking a minute plus.

bbehling commented 7 years ago

I've seen similar issues using ArcGIS sever tiles and dynamic services.

One issue is where the last pending request is drawn on the map, even after calling the setLayers() method with no layers turned on. So, we end up with tiles drawn when actually there shouldn't be any map tiles present on the map.

Another issue is in Internet Explorer 11. All requests are stuck in a pending state and never draw on the map, but that is occurring because I had have to use the es6-promise polyfill to fix issues with bing maps plugins.

Lastly, I've seen issues where tiles will not draw in the correct on the map. We consume multiple services, and those are placed in the map in a particular order. If one of those services takes longer to finish a request then other services, that particular service is rendered underneath the services that completed first, when what should happen is all services should be rendered in the same order they were added to the map, regardless of when the requests finished.

It seems request promises are not honoring the order the services are in, or just issues with handling promises in general? All these asynchronous request issues are happening with or without the es6 promise polyfill.

I have a demo app using the ESRI Leaflet API which I ported over from an ESRI JSAPI project. Using the same logic to toggle layers, I've never had a problem with pending requests or services drawn out of order.

jgravois commented 7 years ago

what should happen is all services should be rendered in the same order they were added to the map, regardless of when the requests finished.

that isn't how things work in Leaflet. if you want to get explicit control over the drawing order in Leaflet, you'll need to use custom panes.

bbehling commented 7 years ago

Custom panes applies to all types of layers, not just feature layers?

jgravois commented 7 years ago

yup. they can even be used to draw images on top of graphics.

bbehling commented 7 years ago

Thanks.

Any thoughts on the canceling pending request issue?

jgravois commented 7 years ago

do you have a repro case you can share?

bbehling commented 7 years ago

Custompanes -

Finally got a chance to look at this. The example link custompanes is for feature layers. I need to use this with Dynamic Map Service Layers. The API docs for dynamic layers doesn't mention a pane property.

Do you know how you would set custom panes for a dynamic map service?

Note, I do not want to use a dynamic map service as a feature layer per your example.

jgravois commented 7 years ago

Do you know how you would set custom panes for a dynamic map service?

map.createPane('custom');
L.esri.dynamicMapLayer({
    url: yourUrl,
    pane: 'custom'
  }).addTo(map);

http://jsbin.com/xohihoduci/edit?html,output

The API docs for dynamic layers doesn't mention a pane property.

this is because the pane property is inherited all the way down from L.ImageOverlay > L.Layer and we don't typically reproduce Leaflet's core documentation.

you're absolutely right though, its confusing that we document the property for L.esri.featureLayer. my preference would be remove it there rather than add it to L.esri.dynamicMapLayer

bbehling commented 7 years ago

Thanks for that info.

bbehling commented 7 years ago

Here is an example of a dynamic layer not canceling a request.

http://plnkr.co/edit/1l0leC8HN1YJskaYDYZX

Toggling the checkbox calls the L.esri.dynamicMapLayer.setLayers() method. If the checkbox is checked, 4 layers are shown on the map. If the checkbox is not checked, all layers are removed.

If you toggle on the checkbox and immediately toggle off the checkbox, no layers should be showing on the map, but they still are loaded. (If you look at this in preview mode, its easier to reproduce the issue because its a larger area and the map tile request takes a little longer)

It seems the callback handler (or promises) is not handling the callbacks (promises) in the correct order. Is leaflet using promises for theses requests?

Note, this behavior does not occur in the ESRI JSAPI.

bbehling commented 7 years ago

I was experimenting with this plugin

https://github.com/SVoyt/esri-leaflet-dynamic-advanced

That handles canceled requests as expected.

Also just found in my example the map services references it not publicly visible. The roads map service should be replaced with a public facing one.

jfolds commented 6 years ago

I am running into this issue (previous network requests not cancelled, and causing new requests to stall)

@bbehling mentioned that the plugin above handles this correctly. Is there anyway to implement what is working in the plugin directly into esri-leaflet?

I am having trouble finding the code in the plugin above that would handle this.

Any ideas appreciated, thanks!

bbehling commented 6 years ago

Looks like the esri-leaflet-dynamic-advanced implements a tally of requests and deleting the image source. See this._requestCounter in the _imageLoaded method.

Perhaps a better implementation would be to cancel pending requests from whatever mechanism is making the request, probably jQuery and use the jqXHR.abort() method.

Or possibly using these Leaflet methods // Cancels any pending http requests associated with the tile. tile.el.setAttribute('src', Util.emptyImageUrl); https://github.com/Leaflet/Leaflet/issues/4149

"Basically, setting the img element's src to an empty image makes the browser abort the loading " https://github.com/Leaflet/Leaflet/issues/4149

I recently had to implement something similar with Angular http services and ESRI's JSAPI when overriding a getImageUrl method for the Dynamic Map Layer class. Canceling pending http service requests worked perfectly for that. Maybe the same idea would work here.

vajnorcan commented 6 years ago

@bbehling I know that you guys are talking about the image tiles, but have you ever attempted to cancel the pending requests made by the feature layer? Imagine that someone checks on the feature layer, this will send as many requests as there is tiles and then he decides to turn it off... map is still in the 'updating' mode and only triggers the 'map-updated' once all the requests are finished. Do you know how to force/trick the map to forget about those pending requests? thanks

g-cheishvili commented 3 years ago

We have a huge amount of data on our arcgis server and when user navigates on leaflet map requests are jamming up and at some point map becomes unusable. I do not know why this issue did not get any update since 2018, as this is a important one

davetapley commented 3 years ago

Experiencing this very badly with the FEMA NFHL MapServer.

Users will often toggle on (triggering a setLayers), then toggle off when nothing happens (because it's loading behind the scenes), then the loading will finish resulting the in layers being show. The layer toggle in our UI is then inconsistent with the map. One work around is to watch for on("load", events to resynchronize with the UI, but it's poor UX.

pmacMaps commented 3 years ago

It may be an issue with that web service. I have used it in various Esri-based apps (Story Maps, Web AppBuilder), and that service is slow as molasses in those as well.