如何从 AngularJS 应用程序中的控制器观察服务中的变量?
How to watch variable in service from controller within AngularJS application?
我正在编写应用程序功能,在执行请求时设置加载 gif(出于学习目的)。我使用 AngularJS 1.4.5、"Controller as" 语法和 John Papa 风格指南。
所以,我写了一个 拦截器 将当前请求的数量传递给服务:
(function () {
'use strict';
angular
.module('eventApp')
.factory('requestInterceptorService', requestInterceptorService);
requestInterceptorService.$inject = ['$q', 'loadingService'];
function requestInterceptorService($q, loadingService) {
var numLoadings = 0;
var requestInterceptorServiceFactory = {
request: request,
response: response,
responseError: responseError
};
return requestInterceptorServiceFactory;
function request(config) {
numLoadings++;
loadingService.setLoaderStatus(numLoadings);
return config || $q.when(config);
}
function response(response) {
numLoadings--;
loadingService.setLoaderStatus(numLoadings);
return response || $q.when(response);
}
function responseError(response) {
numLoadings--;
loadingService.setLoaderStatus(numLoadings);
return $q.reject(response);
}
}
})();
这是我的 loading.service,带有标志 isLoadgerEnabled,指示我们是否需要显示加载图像:
(function () {
'use strict';
angular
.module('eventApp')
.factory('loadingService', loadingService);
function loadingService() {
var isLoaderEnabled = false;
var loadingServiceFactory = {
setLoaderStatus: setLoaderStatus,
getLoaderStatus: getLoaderStatus,
isLoaderEnabled: isLoaderEnabled
};
return loadingServiceFactory;
function setLoaderStatus(numberOfRequests) {
var status = false;
if (numberOfRequests === 0) {
status = false;
}
if (numberOfRequests !== 0) {
status = true;
}
isLoaderEnabled = status;
}
function getLoaderStatus() {
return isLoaderEnabled;
}
}
})();
以上代码对我有用。
在视图中,我有 div 加载图像和 ng-show 指令,它监听来自 index 控制器的标志:
<div id="loaderDiv">
<img src="client/assets/img/loader.gif" class="content-loader"
ng-show="index.isLoaderEnabled" />
</div>
.controller('indexController', indexController);
indexController.$inject = ['$location', 'authService', 'authModal', 'loadingService', '$scope'];
function indexController($location, authService, authModal, loadingService, $scope) {
var vm = this;
vm.isLoaderEnabled = loadingService.isLoaderEnabled;
//code with other functionality
$scope.$watch(function () {
return loadingService.isLoaderEnabled;
}, function (newValue) {
vm.isLoaderEnabled = newValue;
});
}
})();
我的问题:vm.isLoaderEnabled 没有使用服务更新 (实际上 vm.isLoaderEnabled 总是错误的)而且我不确定问题出在哪里。
我想为此功能编写高效而优雅的解决方案,也许没有 $scope (如果可能的话)。
我已准备好接受问题、重构建议或更好的想法来绑定数据以查看。
好的,我设法找到了解决问题的方法。
起初我想指出loadingService中的那部分代码:
var loadingServiceFactory = {
setLoaderStatus: setLoaderStatus,
getLoaderStatus: getLoaderStatus,
isLoaderEnabled: isLoaderEnabled//<------1 line
};
return loadingServiceFactory;//<------2 line
在1行我复制 isLoaderEnabled到属性 isLoaderEnabled,在2行我return吧。所以 loadingController 得到我的加载标志的 copy。如果我早点发现我的代码可以工作(因为我尝试了很多其他解决方案)。
所以,解决方案。我使用观察者模式解决了这个问题:这在 Angular 中不是很好的做法,但它有效(无论如何我将来会覆盖我的代码)。
requestInterceptor - 没有改变
加载服务:
(function () {
'use strict';
angular
.module('eventApp')
.factory('loadingService', loadingService);
function loadingService() {
var isLoaderEnabled = false;
var callbacks = [];
var loadingServiceFactory = {
setLoaderStatus: setLoaderStatus,
getLoaderStatus: getLoaderStatus,
register: register
};
return loadingServiceFactory;
function setLoaderStatus(numberOfRequests) {
if (numberOfRequests === 0) {
isLoaderEnabled = false;
}
if (numberOfRequests > 0) {
isLoaderEnabled = true;
}
notify();
}
function getLoaderStatus() {
return isLoaderEnabled;
}
function register(callback) {
callbacks.push(callback);
}
function notify() {
callbacks.forEach(function (callback) {
callback();
});
}
}
})();
加载控制器:
(function () {
'use strict';
angular
.module('eventApp')
.controller('indexController', indexController);
indexController.$inject = ['$location', 'authService', 'authModal', 'loadingService'];
function indexController($location, authService, authModal, loadingService) {
/* jshint validthis: true*/
var vm = this;
vm.loading = false;
vm.loaderObserver = function () {
vm.loading = loadingService.getLoaderStatus();
}
loadingService.register(vm.loaderObserver);
//other unnecessary code
};
})();
装载机div
<div id="loaderDiv" ng-show="index.loading" >
<img src="client/assets/img/loader.gif" class="content-loader" />
</div>
我希望这会对某人有所帮助。
我正在编写应用程序功能,在执行请求时设置加载 gif(出于学习目的)。我使用 AngularJS 1.4.5、"Controller as" 语法和 John Papa 风格指南。 所以,我写了一个 拦截器 将当前请求的数量传递给服务:
(function () {
'use strict';
angular
.module('eventApp')
.factory('requestInterceptorService', requestInterceptorService);
requestInterceptorService.$inject = ['$q', 'loadingService'];
function requestInterceptorService($q, loadingService) {
var numLoadings = 0;
var requestInterceptorServiceFactory = {
request: request,
response: response,
responseError: responseError
};
return requestInterceptorServiceFactory;
function request(config) {
numLoadings++;
loadingService.setLoaderStatus(numLoadings);
return config || $q.when(config);
}
function response(response) {
numLoadings--;
loadingService.setLoaderStatus(numLoadings);
return response || $q.when(response);
}
function responseError(response) {
numLoadings--;
loadingService.setLoaderStatus(numLoadings);
return $q.reject(response);
}
}
})();
这是我的 loading.service,带有标志 isLoadgerEnabled,指示我们是否需要显示加载图像:
(function () {
'use strict';
angular
.module('eventApp')
.factory('loadingService', loadingService);
function loadingService() {
var isLoaderEnabled = false;
var loadingServiceFactory = {
setLoaderStatus: setLoaderStatus,
getLoaderStatus: getLoaderStatus,
isLoaderEnabled: isLoaderEnabled
};
return loadingServiceFactory;
function setLoaderStatus(numberOfRequests) {
var status = false;
if (numberOfRequests === 0) {
status = false;
}
if (numberOfRequests !== 0) {
status = true;
}
isLoaderEnabled = status;
}
function getLoaderStatus() {
return isLoaderEnabled;
}
}
})();
以上代码对我有用。 在视图中,我有 div 加载图像和 ng-show 指令,它监听来自 index 控制器的标志:
<div id="loaderDiv">
<img src="client/assets/img/loader.gif" class="content-loader"
ng-show="index.isLoaderEnabled" />
</div>
.controller('indexController', indexController);
indexController.$inject = ['$location', 'authService', 'authModal', 'loadingService', '$scope'];
function indexController($location, authService, authModal, loadingService, $scope) {
var vm = this;
vm.isLoaderEnabled = loadingService.isLoaderEnabled;
//code with other functionality
$scope.$watch(function () {
return loadingService.isLoaderEnabled;
}, function (newValue) {
vm.isLoaderEnabled = newValue;
});
}
})();
我的问题:vm.isLoaderEnabled 没有使用服务更新 (实际上 vm.isLoaderEnabled 总是错误的)而且我不确定问题出在哪里。 我想为此功能编写高效而优雅的解决方案,也许没有 $scope (如果可能的话)。 我已准备好接受问题、重构建议或更好的想法来绑定数据以查看。
好的,我设法找到了解决问题的方法。 起初我想指出loadingService中的那部分代码:
var loadingServiceFactory = {
setLoaderStatus: setLoaderStatus,
getLoaderStatus: getLoaderStatus,
isLoaderEnabled: isLoaderEnabled//<------1 line
};
return loadingServiceFactory;//<------2 line
在1行我复制 isLoaderEnabled到属性 isLoaderEnabled,在2行我return吧。所以 loadingController 得到我的加载标志的 copy。如果我早点发现我的代码可以工作(因为我尝试了很多其他解决方案)。
所以,解决方案。我使用观察者模式解决了这个问题:这在 Angular 中不是很好的做法,但它有效(无论如何我将来会覆盖我的代码)。
requestInterceptor - 没有改变
加载服务:
(function () { 'use strict'; angular .module('eventApp') .factory('loadingService', loadingService); function loadingService() { var isLoaderEnabled = false; var callbacks = []; var loadingServiceFactory = { setLoaderStatus: setLoaderStatus, getLoaderStatus: getLoaderStatus, register: register }; return loadingServiceFactory; function setLoaderStatus(numberOfRequests) { if (numberOfRequests === 0) { isLoaderEnabled = false; } if (numberOfRequests > 0) { isLoaderEnabled = true; } notify(); } function getLoaderStatus() { return isLoaderEnabled; } function register(callback) { callbacks.push(callback); } function notify() { callbacks.forEach(function (callback) { callback(); }); } } })();
加载控制器:
(function () { 'use strict'; angular .module('eventApp') .controller('indexController', indexController); indexController.$inject = ['$location', 'authService', 'authModal', 'loadingService']; function indexController($location, authService, authModal, loadingService) { /* jshint validthis: true*/ var vm = this; vm.loading = false; vm.loaderObserver = function () { vm.loading = loadingService.getLoaderStatus(); } loadingService.register(vm.loaderObserver); //other unnecessary code }; })();
装载机div
<div id="loaderDiv" ng-show="index.loading" > <img src="client/assets/img/loader.gif" class="content-loader" /> </div>
我希望这会对某人有所帮助。