From 6e6f3ece5034dfcb1c5c23cf8e47405c12c55595 Mon Sep 17 00:00:00 2001 From: christopherthielen Date: Tue, 9 Jun 2015 18:22:11 -0500 Subject: [PATCH] feat(future): Allow future states to be retried after a failed lazy load attempt Closes #196 --- src/future.js | 34 ++++++++++++++++++++-------------- test/futureSpec.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/src/future.js b/src/future.js index cc74ed0..54c735e 100644 --- a/src/future.js +++ b/src/future.js @@ -122,25 +122,31 @@ return deferred.promise; } - var promise = $q.when([]), parentFuture = futureState.parentFutureState; + var parentPromises = $q.when([]), parentFuture = futureState.parentFutureState; if (parentFuture && futureStates[parentFuture.name]) { - promise = lazyLoadState($injector, futureStates[parentFuture.name]); + parentPromises = lazyLoadState($injector, futureStates[parentFuture.name]); } var type = futureState.type; var factory = stateFactories[type]; if (!factory) throw Error("No state factory for futureState.type: " + (futureState && futureState.type)); - return promise - .then(function(array) { - var injectorPromise = $injector.invoke(factory, factory, { futureState: futureState }); - return injectorPromise.then(function(fullState) { - if (fullState) { array.push(fullState); } // Pass a chain of realized states back - return array; - }); - }) - ["finally"](function() { // IE8 hack - delete(futureStates[futureState.name]); - }); + + var failedLoadPolicy = factory.$options && factory.$options.failedLazyLoadPolicy || "remove"; + function deregisterFutureState() { delete(futureStates[futureState.name]); } + function errorHandler(err) { + if (failedLoadPolicy === "remove") deregisterFutureState(); + return $q.reject(err); + } + + return parentPromises.then(function(array) { + var factoryPromise = $injector.invoke(factory, factory, { futureState: futureState }); + + return factoryPromise.then(function(fullState) { + deregisterFutureState(); // Success; remove future state + if (fullState) { array.push(fullState); } // Pass a chain of realized states back + return array; + }); + }).catch(errorHandler) } var otherwiseFunc = [ '$log', '$location', @@ -228,7 +234,7 @@ lazyloadInProgress = false; }, function (error) { console.log("failed to lazy load state ", error); - $state.go(fromState, fromParams); + if (fromState.name) $state.go(fromState, fromParams); lazyloadInProgress = false; }); }); diff --git a/test/futureSpec.js b/test/futureSpec.js index 5ce3eee..abdf699 100644 --- a/test/futureSpec.js +++ b/test/futureSpec.js @@ -181,5 +181,48 @@ describe('futureState', function () { _futureStateProvider.futureState(futureState("nourl.issue167", undefined, undefined, "iframe")); // no url testGo("nourl.issue167"); }); + + // Test 1 for enhancement issue #196 + it("should remove future states that properly load", function() { + var name = "top.foo"; + + expect($futureState.get()[name]).toBeDefined(); + + $state.go(name); + $q.flush(); + + expect($state.current.name).toBe(name); + expect($futureState.get()[name]).toBeUndefined(); + }); + + // Test 2 for enhancement issue #196 + it("should remove future states that failed to load, if no policy is set", function() { + var name = "top.bar"; + + expect($futureState.get()[name]).toBeDefined(); + + $state.go(name); + $q.flush(); + + expect($state.current.name).toBe(""); + expect($futureState.get()[name]).toBeUndefined(); + }); + + // Test 3 for enhancement issue #196 + it("should remove future states that failed to load, if no policy is set", function() { + var name = "top.bar"; + + var factory = function (futureState) { return $q.reject("doesntwork"); }; + factory.$options = { failedLazyLoadPolicy: "retain" }; + _futureStateProvider.stateFactory('doesntwork', factory); + + expect($futureState.get()[name]).toBeDefined(); + + $state.go(name); + $q.flush(); + + expect($state.current.name).toBe(""); + expect($futureState.get()[name]).toBeDefined(); + }) }); });