Below the Radar Below the Radar - 7 months ago 31
Javascript Question

Promise.all() - Do something after multiple event listeners are triggered

I am using a cartographic API that implement a

layer
object. There is an event on the layer that is fired when the layer's
features
finished loading. This process is asynchronous.

I want to use Promise to handle the moment when features of each map's layers are loaded. However sometimes layer's features are already loaded before I have added the listener and sometimes not.

I am trying to use
Promise.all()
like below, but I am not sure if its the best way to achieve what I am trying to do.

var layers = [layer1, layer2, layer3];
var promises = [];

Promise.all(promises).then(function() {
//here am I sure that all layers features are loaded?
doSomething();
});

layers.forEach(function(layer) {
if (layer.features.length > 0) {
//features are already loaded
onFeaturesLoaded();
} else {
//features not loaded yet, a one time event listener is added
layer.addOneTimeEventListener(layer.EVENTS.FEATURES_LOADED, onFeaturesLoaded, layer);
}
});

function onFeaturesLoaded() {
return new Promise(function(resolve) {
resolve();
});
};

ajm ajm
Answer

That seems like a perfectly valid use of Promise.all.

One thing to note: your forEach loop will need to return promises in the addEventListener case so Promise.all can operate on them.

Using map() might be a little bit easier for you as you'll have a nice Array to pass right into Promise.all.

Promise.all(layers.map(function(layer){ 
    if(layer.features.length === 0){
        return new Promise(function(resolve, reject){
            layer.addEventListener(layer.EVENTS.FEATURES_LOADED, function(){ resolve(); }, layer);
        });
    }
    else{
        return new Promise(function(resolve, reject){ resolve(); });
    }
})
.then(function(){ 
    // Everything is loaded at this point.
});

That will give you an array of promises for layers that have yet to load and promises that resolve immediately for those already loaded.

Comments