Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy loading is not being used correctly #41

Open
yjukaku opened this issue Oct 29, 2015 · 9 comments
Open

Lazy loading is not being used correctly #41

yjukaku opened this issue Oct 29, 2015 · 9 comments
Assignees

Comments

@yjukaku
Copy link

yjukaku commented Oct 29, 2015

The resolve method of angular-ui router is a map of functions. Each function should return a promise. When every function in the map has resolved, the state can continue loading.

However, in sb-admin, there are multiple calls like this in app.js:

resolve: {
            loadMyDirectives : function($ocLazyLoad){
                return $ocLazyLoad.load(
                {
                    name:'myApp',
                    files:[
                    'bower_components/moment/moment.js',
                    ]
                })
                ,
                $ocLazyLoad.load(
                {
                  name:'angulartics-google-analytics',
                  files:['bower_components/angulartics-google-analytics/dist/angulartics-google-analytics.min.js']
                })  //since there is a comma missing here, the return statement is triggered and the rest is ignored
                $ocLazyLoad.load(
                {
                   name:'toggle-switch',
                   files:["bower_components/angular-toggle-switch/angular-toggle-switch.min.js",
                          "bower_components/angular-toggle-switch/angular-toggle-switch.css"
                      ]
                })
        }

Calling $ocLazyLoad.load will load the items, but doing it repeatedly doesn't cause the state to wait for all the load calls to resolve, it only waits for the last one.

FURTHER, there are commas missing between some of the load calls after a return statement. This causes javascript to do ASI (automatic semicolon insertion), effectively ignoring any $ocLazyLoad.load items after the first missing comma.

*Note: This is my understanding, I may be wrong about how lazy load works. But the ASI is definitely happening, since you can write whatever valid JS you want after the missing comma and it never gets executed.

@garciaba
Copy link

But if you write a comma between the different lazyloaders it should work, right?

I don't really understand why there is no comma between loaders in the dashboard state, but there is (or should be, at least I must put it to add more libraries) in the other states.

Anyway, I'm getting an issue that is probably related to this. When switching between views, sometimes it throws an error saying that the controller does not exist (probably not loaded yet). If yor refresh the page it works perfectly, but I don't know what is happening there. I guess that the loader of that specific state is not yet loaded, but I'm not totally sure...

¿Any way to keep the view waiting until all directives/controllers are loaded?

@yjukaku
Copy link
Author

yjukaku commented Mar 16, 2016

It's not just the commas that are needed, but rather the whole thing needs
to be wrapped in a Promise.all() and returned.
On Mar 16, 2016 5:39 AM, "mikeyxoel" [email protected] wrote:

But if you write a comma between the different lazyloaders it should work,
right?

I don't really understand why there is no comma between loaders in the
dashboard state, but there is (or should be, at least I must put it to add
more libraries) in the other states.

Anyway, I'm getting an issue that is probably related to this. When
switching between views, sometimes it throws an error saying that the
controller does not exist (probably not loaded yet). If yor refresh the
page it works perfectly, but I don't know what is happening there. I guess
that the loader of that specific state is not yet loaded, but I'm not
totally sure...

¿Any way to keep the view waiting until all directives/controllers are
loaded?


You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub
#41 (comment)

@garciaba
Copy link

Is there anyway to fix this issue? I'm quite new to AngularJS

@yjukaku
Copy link
Author

yjukaku commented Mar 16, 2016

Yep. Every $ocLazyLoad.load() returns an object (Promise object). Take every Promise object returned, and put it into an array. Then call $q.all(promisesArray), and return the result of that call.

This is necessary because AngularUI Router (which is what SBAdminAngular uses for routing URLs to states) expects a Promise object to return from the resolve function. If you have multiple promises that need to be finished from within resolve function, you can wrap it in $q.all. ($q is the Promise library for Angular)

@garciaba
Copy link

Could you make a Plunkr, or just a small example right here? I'm trying to do it but I just can't get it work. Would be great, thank you!

@yjukaku
Copy link
Author

yjukaku commented Mar 16, 2016

resolve: {
            loadMyDirectives : function($ocLazyLoad){
                var prom1 = $ocLazyLoad.load(
                {
                    name:'myApp',
                    files:[
                    'bower_components/moment/moment.js',
                    ]
                });
                var prom2 = $ocLazyLoad.load(
                {
                  name:'angulartics-google-analytics',
                  files:['bower_components/angulartics-google-analytics/dist/angulartics-google-analytics.min.js']
                });
                var prom3 = $ocLazyLoad.load(
                {
                   name:'toggle-switch',
                   files:["bower_components/angular-toggle-switch/angular-toggle-switch.min.js",
                          "bower_components/angular-toggle-switch/angular-toggle-switch.css"
                      ]
                });
                //prom1 "resolves" when it's files have all loaded
                //prom2 "resolves" when it's files have all loaded
                //etc.
                var promArray = [prom1, prom2, prom3]; //an array of Promise objects
                //we must return a single promise, but we have 3.  How do we solve this? It's built into the $q library from Angular.
                return $q.all(promArray); //create and return a wrapping Promise that resolves only when all the promises in the array have resolved.
        }

@garciaba
Copy link

I'm doing as you said, but for some reason the page just doesn't load, it stays white... There is not even error in the console. If I set a debugger in the $stateProvider it triggers, but I don't know...

// Now we set up the states
        $stateProvider
            .state('dashboard', { //parent view
                url: '/dashboard',
                templateUrl: 'views/dashboard/main.html',
                resolve: { // Any property in resolve should return a promise and is executed before the view is loaded
                    loadMyDirectives: function ($ocLazyLoad) {
                        var prom1 = $ocLazyLoad.load({
                            name: 'sbAdminApp',
                            files: [
                    'scripts/directives/header/header.js',
                    'scripts/directives/header/header-notification/header-notification.js',
                    'scripts/directives/sidebar/sidebar.js',
                    'scripts/directives/sidebar/sidebar-search/sidebar-search.js'
                    ]
                        });
                        var prom2 = $ocLazyLoad.load({
                            name: 'toggle-switch',
                            files: ["bower_components/angular-toggle-switch/angular-toggle-switch.min.js",
                          "bower_components/angular-toggle-switch/angular-toggle-switch.css"
                      ]
                        });
                        var prom3 = $ocLazyLoad.load({
                            name: 'ngAnimate',
                            files: ['bower_components/angular-animate/angular-animate.js']
                        });
                        var prom4 = $ocLazyLoad.load({
                            name: 'ngCookies',
                            files: ['bower_components/angular-cookies/angular-cookies.js']
                        });
                        var prom5 = $ocLazyLoad.load({
                            name: 'ngResource',
                            files: ['bower_components/angular-resource/angular-resource.js']
                        });
                        var prom6 = $ocLazyLoad.load({
                            name: 'ngSanitize',
                            files: ['bower_components/angular-sanitize/angular-sanitize.js']
                        });
                        var prom7 = $ocLazyLoad.load({
                            name: 'ngTouch',
                            files: ['bower_components/angular-touch/angular-touch.js']
                        });
                        var prom8 = $ocLazyLoad.load({
                            name: 'googlechart',
                            files: ['bower_components/angular-google-chart/ng-google-chart.js']
                        });

                        var promArray = [prom1, prom2, prom3, prom4, prom5, prom6, prom7, prom8];

                        return $q.all(promArray); 

                    }
                }

@yjukaku
Copy link
Author

yjukaku commented Mar 16, 2016

You have to inject $q into your loadMyDirectives function like loadMyDirectives: function ($ocLazyLoad, $q). If you need further help, post a SO question. 👍

@garciaba
Copy link

Thank you, it totally works, and very good actually! You should make a pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants