0

I'm working on a angularJS-based tool for building charts and am wanting to create a user-overridable config system — i.e., default values are loaded from one config file, which are then overridden if another config file exists.

Here's what I have so far:

angular.module('axisJSApp')
  .provider('configProvider', function () {
    this.$get = function axisJSConfig($http, $q) {
      var defaultConfig = $http.get('default.config.yaml');
      var userConfig = $http.get('config.yaml');

      return $q.all([defaultConfig, userConfig]).then(function(values){
        var defaultConfigYaml = jsyaml.safeLoad(values[0].data);
        var userConfigYaml = jsyaml.safeLoad(values[1].data);
        return angular.extend(defaultConfigYaml, userConfigYaml);
      });
    };
  });

Then in my controller:

angular.module('axisJSApp')
  .controller('MainCtrl', function (configProvider, $scope) {
    configProvider.then(function(appConfig){
      console.dir(appConfig); // Config loaded, everything else happens.
    });
  });

This all works fine if both default.config.yaml and config.yaml exist. My question is, how do I cause $q.all() to fail gracefully if config.yaml doesn't exist?

Additionally, is there any way of synchronously loading the config file so I don't have to wrap my entire controller in a .then()?

Thanks!

aendra
  • 5,286
  • 3
  • 38
  • 57

1 Answers1

1

One way I can think of to handle the non-existence of config.yaml gracefully is:

var userConfig = $http.get('config.yaml').then(
    function(response) {
        return response.data;
    },
    function(response) {
        if( response.status === 404 ) {
            response.data = {};
            return response;
        }
        else {
            return $q.reject(response);
        }
    }
);

return $q.all([defaultConfig, userConfig]).... // AS BEFORE

So you manually fix the "does not exist" case, by returning an empty object in response.data (or anything that suits your needs).

I cannot think of an elegant way to load the config files synchronously; if you are using ngRoute, you could use the resolve configuration for the route (more here) to feed the controller with the data before it starts.

Nikos Paraskevopoulos
  • 39,514
  • 12
  • 85
  • 90
  • That's all super helpful. Using ngRoute is an interesting idea, hadn't considered that. Thank you! – aendra Oct 22 '14 at 15:21