I am attempting to add multiple baselayers to a Cesium map from a set of values in a database. I would like the javascript to just iterate over them and then add them. Here is the static code example from Cesium:
var imageryViewModels = [];
imageryViewModels.push(new Cesium.ProviderViewModel({
name : 'Open\u00adStreet\u00adMap',
iconUrl : Cesium.buildModuleUrl('openStreetMap.png'),
tooltip : 'OpenStreetMap (OSM)',
creationFunction : function() {
return Cesium.createOpenStreetMapImageryProvider({
url : 'https://a.tile.openstreetmap.org/'
});
}
}));
imageryViewModels.push(new Cesium.ProviderViewModel({
name : 'Black Marble',
iconUrl : Cesium.buildModuleUrl('blackMarble.png'),
tooltip : 'outlines of civilization',
creationFunction : function() {
return Cesium.createTileMapServiceImageryProvider({
url : 'https://cesiumjs.org/blackmarble',
credit : 'B Observatory',
flipXY : true
});
}
}));
Super simple so far with a set of values that are static. Here is where it gets tricky, I want to loop over a set of values and then push the ProviderViewModels on to the array. Like this -
var imageryViewModels = [];
baseLayers = HashOfValuesFromDatabase;
for(int i=0; i<baseLayers.length; i++{
imageryViewModels.push(new Cesium.ProviderViewModel({
name : baseLayers[i].name,
iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl),
tooltip : baseLayser[i].toolTip,
creationFunction : function() {
return Cesium.createOpenStreetMapImageryProvider({
url : baseLayers[i].url // ***** this value always the last value ****
});
}
}));
}
The problem is that the javascript closure is causing me problems and every one of my imageryViewModels is the last value in the baseLayer.url object. Cesium needs this to be a function here. Is there a way to keep this a function but get the values of the iterated baseLayer.url?
Ben Aston's answer is the correct approach here. He didn't try running it, and there's an extra semicolon after the
}(i))
that's illegal inside an argument list, and there are also some problems he copy-pasted from your original question. Here's the corrected version, and I did get this to run:The reason this fixes the
url
parameter is because of the IIFE (immediately invoked function expression) that usesi
as a parameter. This creates a new JavaScript closure per iteration through the loop, which is expensive, but is required so that each individualcreate
function gets its very own closure with its own copy of the value ofi
from that particular iteration of the loop. Without this, there is only one closure with only onei
variable, and by the time any of the create functions are actually called, the loop is long since finished and the value ofi
has reached its maximum.