How to properly check if a FeatureLayer object has been loaded?

6896
11
04-27-2018 01:46 PM
SamuelAbati
New Contributor III

So, I know the documented way to do it would be like this :

const fl = new featureLayer(url);
fl.on('load', () => {
   doSomething();
})‍‍‍‍‍‍‍‍

But there is a problem with the approach above, if the featureLayer has already loaded between its creation and the event binding, doSomething() will never trigger.

This would be solved by simply having a callback parameter on the featureLayer constructor, which doesn't.

So, for now I'm using the following solution :

const fl = new featureLayer(url);
if(!fl.loaded){             
    fl.on('load', () => {                    
        doSomething();                
    })
}else{                
    doSomething();
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

But there's also a very nasty possible error with my temporary solution, it can happen that the featureLayer will load between the if/else check, and then doSomething() will never trigger.

Is there an actual solution to this? Is this a bug? Am I missing something?

Here's a pen showing the issue : FeatureLayer 

I'm using the setTimeout to force the layer to load, in our company the arcgis server is local so they load really fast, before binding the event as I stated above

0 Kudos
11 Replies
FreddieGibson
Occasional Contributor III

Hi Samuel, 

I do apologize for dragging this out, but I still don't quite understand how the emit would not work. If you have time I'd be more than happy to have you log a support ticket and we can discuss this in more specifics. I wrote up a sample at http://jsbin.com/tuniwel/1/edit?js,output to test out my logic. Below is the relevant JS code. 

var url = "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0";

require([
    "esri/map",
    "esri/layers/FeatureLayer",
    "dojo/domReady!"
  ],
  function(
    Map,
    FeatureLayer
  ) {

    // Create a map
    var map = new Map("map", {
      basemap: "hybrid",
      center: [-82.44109, 35.6122],
      zoom: 17
    });

    // Create a layer object
    var layer = new FeatureLayer(url);

    /* I'm using the timeout to force the issue to 
        occur. The application will wait 3 seconds
        before wiring in the load event. This will
        cause the load event to never fire. */
    setTimeout(function() {
      
      var msg = "using load event.";

      // Wire into the load event. 
      layer.on("load", function() {
        alert("Layer has loaded " + msg); 
      });        

      // Check if the layer has loaded. 
      /* If this is still false
         then we're certain that the event was wired before the 
         layer finished loading and we can wait for it to fire
         naturally. */
      if (!layer.loaded) { alert("Waiting on load event to fire"); }
      
      /* On the other hand, if this is true then assume that the 
          load event was wired after the layer has already loaded. 
          In this case we can force the load event to fire.
       */ 
      else {
        alert("Layer was loaded before we could finish wiring event.");

        msg = "using emit to force load event.";
        // Force the load event to fire
        layer.emit("load", {"layer":layer});
      }
      
      
    }, 3000);
  
  
    map.addLayer(layer);

});

You should note that if I specify 3000 on line 56 that 1) the layer loads before I can wire into the the load event and 2) the code is able to use emit to force the load event to fire. You should also note that if you change line 56 to zero that the load event fires as we would normally expect.

Would you be able to modify this so that we unable to get the load event to fire? If you can then I would be able to easily display this issue to our developers so that we determine how to address this issue. I do understand that at the moment you're committed to using version 3.x of the JavaScript API. Although it's a moot point, I do feel that promises would resolve this issue in 4.x as they would implement what you're wanting to add to the FeatureLayer class in 3.x. 

0 Kudos
ReneRubalcava
Frequent Contributor

I think I'm a little confused. Have you seen problems with either of these approaches?

// should be fine
const fl = new featureLayer(url);
fl.on('load', () => {
   doSomething();
})


// extra cautious method
const fl = new featureLayer(url);
if(!fl.loaded){             
    fl.on('load', () => {                    
        doSomething();                
    })
}else{                
    doSomething();
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Neither of those methods should be an issue. The initialization of the layer is synchronous, but there extra cautious way is typically used when you try to use an event listener somewhere else in your code and not immediately after creating the layer.

There should be no concerns with the two approaches above.

0 Kudos