0

I'm trying to lazy-load controllers inside route by using resolve:

.when('/somepage', {
        resolve: {
            load: function (loadDependencies, $q) {
                return loadDependencies.load(['controllers/myCtrl.js'], [], []);

            }
        },
        templateUrl: 'views/some-template.html'
    })

Here's my loadDependencies factory:

app.factory('loadDependencies', function ($q, $timeout) {

    return {
        load: function (Controllers,cssFiles,modules) {

            var jsPath = "scripts/",
                cssPath = "css/",
                head = document.getElementsByTagName("head")[0],
                deffered = $q.defer(),
                jsReady = 0,
                jsShouldBeReady = Controllers.length;

            Controllers.forEach(function (arrayItem) {
                var js = document.createElement("script");
                js.src = jsPath + arrayItem;
                head.appendChild(js);

                js.onload = function () {
                    jsReady++;
                    if (jsReady == jsShouldBeReady) { // if loaded files equal to controllers length, then they all finished loading - so resolve deffered
                        deffered.resolve(true);
                    }
                };

                js.onerror = function() {
                    alert("Cannot load js files. Pleae try again later");
                }; 
            });

            return deffered.promise;

        }
    }
});

I'm new to angular, but from my understanding - deffered.promise should wait for the promise to resolve? currently it just returns the object. I also tried this:

deffered.promise.then(function () {
   // call back here
});

But i'm failing to understand how to return the resolved value back to the controller.

emc
  • 333
  • 2
  • 16

1 Answers1

1

First - your actual problem: if you want to load a controller when the file arrives lazily, you should read this. You need to register your controllers in order to lazy load them.

As for promises:

I'm a big proponent of always promisifying at the lowest level possible. Your code, performs aggregation on its own with an asynchronous semaphore - that logic is already implemented for you through $q.all which does the same thing, only with better error handling.

function loadScript(url){
    var scr = document.createElement("script");
    scr.src = url;
    var d = $q.defer();
    scr.onload = function(){ d.resolve(scr); };
    scr.onerror = function(e){ d.reject(e); };
    return d.promise;
}

That code is pretty clear, now, you can load multiple promises and wait for them through $q.all:

function load(files){
    return $q.all(files.map(loadScript));
}

load([url1, url2, url2]).then(function(){
    // all files are loaded, just like in your example.
});
Community
  • 1
  • 1
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504