ocombe/ocLazyLoad — pull request #44 by BenBlazely (2014-07-28 12:18:19+00:00)
Title: Fixes for two issues found using nested views in ui-router

Fixed two issues encountered when using ui-router in a specific way.

When a 'root' or parent view is defined and lazy loads modules which are also lazy loaded into a child view, the loader enters a state where it believes files have completed loading before they have.

The 'module redefinition diff' code I added in a previous PR makes this issue worse by not returning a dependency list for modules that it thinks have already loaded.

eg:

In the example below, the 'NavigationView' would be present on every page and feature a login button. Navigation.View.js contains a lazyload module block which instructs it to load User.js. The state is resolved once the 'Navigation.View -> User' dependency is met.

If the user browses to the address http://site.com/login (which is a child of the root node), the app lazy loads a login form into the @content view. Login.View.js also contains a lazyload module block which instructs it to load User.js. The state is resolved once the 'Login.View -> User' dependency is met.

So, the Navigation.View module and the LoginView module both make a series of identical calls to ocLazyLoad to facilitate loading 'User'.

In this case, the page will RANDOMLY fail to load purely based on load latency. Currently the code can return a 'true' result for the file load, but dependencies may still not have been met. This leads to the failure of the second call running very close behind it.

Sometimes it works fine if everything lines up ok and loads quickly. In the absolute best case, it all works, but it ends up loading the User.js file twice. Oops!

The changes in this PR fix both issues. It's been a very frustrating exercise tracking this issue down!

```
// State definition
$stateProvider
.state('root', {
url: '/',
resolve: {
NavigationView: ['$ocLazyLoad', function ($lazy) {
return $lazy.load({
name: 'Navigation.View',
files: ['app/Navigation/Navigation.View.js']
});
}]
},
views: {
'navbar@': {
controller: 'Navigation.View',
templateUrl: 'app/Navigation/Navigation.tpl.html'
},
'content@': {
templateUrl: 'app/Root/Root.tpl.html'
}
}
})

.state('root.login', {
url: 'login',
resolve: {
LoginView: ['$ocLazyLoad', function ($lazy) {
return $lazy.load({
name: 'Login.View',
files: ['app/Login/Login.View.js']
});
}]
},
views: {
'content@': {
controller: 'Login.View',
templateUrl: 'app/Login/Login.tpl.html'
}
}
});
```

So, in summary:

Fix 1: Fixed a mistake in the module-redefinition detection block that was causing a 0 dependency return on modules requested from the lazy loader more than once (ie: from different routes).

Fix 2: Added further safeguards to the fileCache to ensure that files loaded very close to each other (ie: in two views on the same page defined in ui-router) do not double-load. This is accomplished by storing the deferred.promise of the file load process in the fileCache rather than a boolean.

B