我创建了一些角度的factorys,它们存储了一些数据并提供了一些方法。如果我的应用程序视图发生了变化,我将检查是否在factorys中存在某些数据,以及是否允许根据数据显示该视图。
在方法中,我可以调用另一个工厂的方法。 $ basket.getBasketTotal()。value - >此方法返回空值而没有延迟。该值存储在工厂的属性中。 $ basket工厂具有与$ bookingSteps相同的结构,它只包含其他值。
如果我从视图控制器调用工厂方法,似乎工厂的数据不存在。如果我调试它,则存在数据,因为调试会使执行速度变慢。所以对我而言,问题似乎与生命周期和工厂状态有关。
如果我将$ timeout arround包装并且延迟调用工厂方法,那么app的行为就像预期的那样。但这不是一个很好的解决方案。
有人知道如何解决这种问题吗?
app.controller('checkoutController', ['$scope', '$timeout', '$bookingStepsFactory', function ($scope, $timeout, $bookingStepsFactory) {
$timeout(function () {
$bookingStepsFactory.isAssessable();
}, 1500);
}]);
app.factory('$bookingStepsFactory', ['$rootScope', '$route', '$location', '$rateSearchFactory', '$global', 'localStorageService', '$basket',
function ($rootScope, $route, $location, $rateSearchFactory, $global, localStorageService, $basket) {
/**
* Stored the current visible booking step, the number of maximum steps available
* and the routes for each step
* @type {{currentStep: number, maxSteps: number, routes: Array}}
*/
var bookingStepsSettings = {
currentStep: 1,
maxSteps: 5,
routes: []
}, numberOfProperties = 0, tmpMaxStepsFromRoutes = 0, key;
//Number of hotels within this channel type
numberOfProperties = $global.getHotelData().length;
for (key in $route.routes) {
if ($route.routes.hasOwnProperty(key)) {
if ($route.routes[key].bookingStep) {
//Find the highest step number within routes
if (tmpMaxStepsFromRoutes === 0) {
tmpMaxStepsFromRoutes = $route.routes[key].bookingStep;
} else if ($route.routes[key].bookingStep > tmpMaxStepsFromRoutes) {
tmpMaxStepsFromRoutes = $route.routes[key].bookingStep;
}
//If the minimum number of results needed for the route is lower than the number of hotels,
//add route to collection. If there is only one hotel, all routes needing mor than one result, will
//not be added. i.e. The hotel selection is not needed for one hotel.
if (!$route.routes[key].disabled && $route.routes[key].minResults && $route.routes[key].minResults <= numberOfProperties) {
bookingStepsSettings.routes.push({
step: $route.routes[key].bookingStep,
path: key,
minResults: $route.routes[key].minResults,
name: $route.routes[key].stepName,
disabled: $route.routes[key].disabled || false,
needItemsInBasket: $route.routes[key].needItemsInBasket || false
});
} else if (!$route.routes[key].disabled && !$route.routes[key].minResults) {
bookingStepsSettings.routes.push({
step: $route.routes[key].bookingStep,
path: key,
minResults: $route.routes[key].minResults,
name: $route.routes[key].stepName,
disabled: $route.routes[key].disabled || false,
needItemsInBasket: $route.routes[key].needItemsInBasket || false
});
}
}
}
}
bookingStepsSettings.maxSteps = tmpMaxStepsFromRoutes;
function save() {
localStorageService.set('bookingStepsSettings', bookingStepsSettings);
localStorageService.set('numberOfProperties', numberOfProperties);
}
function init() {
var date = localStorageService.get('rateDate'), obj,
currentDate = new Date();
if (date) {
if (new Date(parseInt(date, 10)).getTime() + (5 * 60 * 1000) >= currentDate.getTime()) {
bookingStepsSettings = localStorageService.get('bookingStepsSettings');
numberOfProperties = parseInt(localStorageService.get('numberOfProperties'));
}
var current = $route.current.$$route.originalPath, numberOfSearchResults = $rateSearchFactory.resultsAvailable(), i = 0;
for (i = 0; i < bookingStepsSettings.routes.length; i++) {
if (bookingStepsSettings.routes[i].path === current) {
bookingStepsSettings.currentStep = bookingStepsSettings.routes[i].step;
}
}
}
}
init();
/**
* Function that returns a route based on the step number
* @param step (integer value between 1 and maxSteps)
* @returns {*}
*/
function getPath(step) {
var i = 0, result;
for (i = 0; i < bookingStepsSettings.routes.length; i++ ) {
if (bookingStepsSettings.routes[i].step === step) {
result = bookingStepsSettings.routes[i];
}
}
return result;
}
/**
* Function that returns a route based on the min results. This is needed in case we get one result
* in a channel with multiple hotels, to ignore the hotel selection
* @param results
* @returns {*}
*/
function getStepByMinResults (results) {
var i = 0, result;
if (results === 0) {
for (i = 0; i < bookingStepsSettings.routes.length; i++ ) {
if (bookingStepsSettings.routes[i].bookingStep === 1) {
result = bookingStepsSettings.routes[i];
break;
}
}
} else {
for (i = 0; i < bookingStepsSettings.routes.length; i++) {
if (bookingStepsSettings.routes[i].minResults <= results) {
result = bookingStepsSettings.routes[i];
break;
}
}
}
return result;
}
/**
* If location will change, check if the new URL is part of the booking steps. If yes, update the current
* booking step.
*/
$rootScope.$on('$locationChangeStart', function(event, newUrl, oldUrl) {
for (var i= 0; i < bookingStepsSettings.routes.length; i++) {
if (newUrl.indexOf(bookingStepsSettings.routes[i].path) >= 0) {
if (bookingStepsSettings.routes[i].step) {
bookingStepsSettings.currentStep = bookingStepsSettings.routes[i].step;
}
}
}
});
/**
* This functions are needed to navigate to the next or previous booking step.
* They are used i.e. by the search box, booking progress
*/
return {
/**
* Is used to navigate to the next booking step
*/
nextStep: function () {
if (bookingStepsSettings.currentStep < bookingStepsSettings.maxSteps) {
var numberOfSearchResults = $rateSearchFactory.resultsAvailable(), tmpStep;
tmpStep = getPath(bookingStepsSettings.currentStep + 1);
if (tmpStep.needItemsInBasket && $basket.getBasketTotal().value < 1) {
return;
}
if (tmpStep.minResults) {
if (tmpStep.minResults <= numberOfSearchResults) {
bookingStepsSettings.currentStep = tmpStep.step;
$location.path(tmpStep.path);
} else {
tmpStep = getStepByMinResults(numberOfSearchResults);
bookingStepsSettings.currentStep = tmpStep.step;
$location.path(tmpStep.path);
}
} else {
$location.path(tmpStep.path);
}
}
save();
},
isAssessable: function() {
var current = $route.current.$$route.originalPath, numberOfSearchResults = $rateSearchFactory.resultsAvailable(), i = 0;
for (i = 0; i < bookingStepsSettings.routes.length; i++) {
if(bookingStepsSettings.routes[i].path === current) {
if (bookingStepsSettings.routes[i].needItemsInBasket && $basket.getBasketTotal().value < 1) {
$location.path(getPath(1).path);
}
if (bookingStepsSettings.routes[i].minResults) {
if (bookingStepsSettings.routes[i].minResults > numberOfSearchResults) {
$location.path(getPath(1).path);
}
}
}
}
},
/**
* Is used to navigate to the previous booking step
*/
previousStep: function () {
if (bookingStepsSettings.currentStep < bookingStepsSettings.maxSteps) {
bookingStepsSettings.currentStep --;
$location.path(getPath(bookingStepsSettings.currentStep));
}
save();
},
/**
* Is used to navigate to a specific booking step
* @param step (Integer between 1 and maxSteps)
*/
goToStep: function (step) {
if (step < bookingStepsSettings.maxSteps) {
var numberOfSearchResults = $rateSearchFactory.resultsAvailable(), tmpStep;
tmpStep = getPath(step);
if (tmpStep) {
if (tmpStep.needItemsInBasket && $basket.getBasketTotal().value < 1) {
return;
}
if (!tmpStep.minResults || tmpStep.minResults && tmpStep.minResults <= numberOfSearchResults) {
bookingStepsSettings.currentStep = tmpStep.step;
$location.path(tmpStep.path);
} else {
tmpStep = getStepByMinResults(numberOfSearchResults);
bookingStepsSettings.currentStep = tmpStep.step;
$location.path(tmpStep.path);
}
}
}
save();
},
/**
* This function returns a copy of all routes within the booking steps.
* @param step (Integer value between 1 and maxSteps)
* @returns {*} Copy of a route object
*/
getBookingRoutes: function () {
return angular.copy(bookingStepsSettings.routes);
},
getCurrentStep: function () {
return angular.copy(bookingStepsSettings.currentStep);
}
};
}]);