I'm sure there is a better way of doing this but here is how I did it:
I stored the layers to be added in a module level variable (layersToAdd) and in each layer onLoad event I pushed the layer in to this array. I then called a function addLayers which checked if the length of addLayers was equal to the total layers to be added. The function sorts the array based on index and then adds them.
For the missing layer in the onError event I removed the item from the array and called addLayer.
There will be a performance hit but I couldn't think of another way. I guess another option would be to add the layers as soon as they are available and then re-order the layers once the total count is reached.
for (var i = 0; i < mapConfig.Services.length; i++) {
layer = this.loadMapService(mapConfig.Services[i], true);
if (layer != null) {
//In Internet Explorer, due to resource caching, the onLoad event is fired as soon as the layer is constructed. Consequently you should check whether the layer's loaded property is true before registering a listener for the onLoad event:
//http://resources.esri.com/help/9.3/arcgisserver/apis/javascript/arcgis/help/jshelp_start.htm#jshelp/inside_events.htm
layer.index = i;
if (layer.loaded) {
this.layersToAdd.push(layer);
this.addLayers();
}
else {
dojo.connect(layer, "onLoad", dojo.hitch(this, function (addlayer) {
this.layersToAdd.push(addlayer);
this.addLayers();
}));
dojo.connect(layer, "onError", dojo.hitch(this, function (err) {
var self = this;
//log error
dojo.forEach(self.configData.Map.Services, function (entry, ix) {
if (entry.ServiceID == layer.id) {
self.configData.Map.Services.splice(ix, 1);
}
}, self);
self.addLayers();
}));
}
}
};
addLayers: function () {
if (this.layersToAdd.length == this.configData.Map.Services.length) {
this.layersToAdd.sort(function(a, b) {
return a.index - b.index;
});
dojo.forEach(this.layersToAdd, function (entry, i) {
this.map.addLayer(entry);
}, this);
this.layersToAdd = null;
}
},
I completely agree that the ESRI samples are now both out of date and misleading. I notice a few samples are updated to AMD but not many. The samples embedding of JavaScript in the HTML is bad practice that most new comers seem to follow. They are just samples to get across ideas, but many don't seem to realise this.
The Basic Map Viewer provided some very useful features for working with ArcGIS online and making a configurable viewer which fits in with ESRI's AGO framework. This is probably quite similar to the app you were looking at though. Also it's also not structured very well in terms of AMD.
For structuring your code in AMD take a look at odoe's AGSModular demo. It also demonstrates how to build Esri JS code in to a single js using r.js (I never got the hang of Dojo build). It's probably going to be quite a steep learning curve if you are new to JS.
I use the HTML5 boiler plate which helps with a number of cross browser issues. It also includes modernizer for feature detection.
For responsive design I haven't found anything out of the box for web maps that is useful.
Best Answer
You're probably looking for the onUpdateEnd event. It fires after all the map layers have been updated. You wouldn't want it to fire every time the map finished updating, so you would probably want to remove the event listener after it fires.