[英]AngularJS multiple Controllers with one Service: Asynchronous errors
在控制器上同时执行功能时,出现一些异步错误。 每个控制器获取一些数据,并调用服务中的方法进行测试。 该服务向控制器返回一个承诺,处理传入的数据,然后解析该承诺。 该服务的代码大纲如下所示:
<!-- language: lang-js -->
//Service that our controller can access
app.service("testing", function($timeout, $q) {
//Test function which takes a group, and returns a promise with the result
this.Test = function(resultsLocation, testList, testFunction) {
//promise we are returning
var deferred = $q.defer();
var i = 0;
//TestCallback loop
TestCallBack = function(testList) {
if (i < testList.length) {
//perform a test on one item of the list
testFunction(testList[i]).then(function() {
//push result back to controller
resultsLocation.push(testList[i].result);
i++;
//show result of that one item with scope update.
//also looks visually pleasing to see test come in
//one at a time
$timeout(function() {
TestCallBack(testList);
}, 100);
});
} else {
//we are done. Resolve promise
deferred.resolve("Done");
}
};
//initiate loop
TestCallBack(testList);
//return promise
return deferred.promise;
};
});//testing Service
然后,我有一些大致如下所示的控制器:
<!-- language: lang-js -->
//Peripheral
app.controller("peripheral#", function($scope, testing) {
//self stuff
$scope.Title = "Peripheral#";
$scope.Summary = "";
$scope.Results = new Array();
//initial lin tests
var DiagnosticsList = [
//test1
//test2
//etc...
];
//Tests routine
$scope.Testing = function() {
//reset results
$scope.Results = new Array();
$scope.Summary = "Testing...";
//Do Tests
testing.Test($scope.Results, DiagnosticsList, CustomTestingFunction1).then(
function(result) {
$scope.Summary = "Testing...";
},
function(error) {
console.log("Error testing Peripheral1");
}
);
};
});
在html中按下按钮时会调用“测试”。 问题是,如果controller1调用“测试”,然后controller2调用“测试”,则诺言将永远不会在controller1中解决。 更糟糕的是,一些测试结果被推入控制器2的结果中。
也许我缺少了一些东西,但是我可能发誓我读过某个地方,当控制器拥有服务时,服务将是它自己的实例。
无论如何,这是一个演示该行为的小伙子: https ://plnkr.co/edit/fE5OD35LaXHWrhv0ohq2?p = preview
单独按“测试”是可以的,但是如果在另一个控制器进行测试时按“测试”,则会出现奇怪的行为,例如,数值被混淆,并且第一个控制器将永远无法完成测试。
问题在于该服务将全局变量TestCallBack
分配给对本地匿名函数的引用。 而是在服务函数范围内将其声明为命名函数。
app.service("testing", function($timeout, $q) {
//Test function which takes a group, and returns a promise with the result
this.Test = function(resultsLocation, testList, testFunction) {
//promise we are returning
var deferred = $q.defer();
var i = 0;
//TestCallback loop
//DONT use global variable
//TestCallBack = function(testList) {
//INSTEAD use a named function
function TestCallBack(testlist) {
if (i < testList.length) {
因此,为了澄清一下,即使将函数声明为var,也可以将其置于全局范围内?
错误是将值设置为未声明的变量。
在执行赋值时,将值分配给未声明的变量会隐式地将其创建为全局变量 (它成为全局对象的属性)。 已声明和未声明的变量之间的区别是:
声明的变量被约束在声明它们的执行上下文中。 未声明的变量始终是全局变量。
在执行任何代码之前创建声明的变量。 在执行分配给它们的代码之前,未声明的变量不存在。
声明的变量是其执行上下文(函数或全局)的不可配置属性。 未声明的变量是可配置的(例如可以删除)。
由于这三个差异,声明变量失败很可能导致意外结果。 因此,建议始终声明变量,而不管它们是在函数范围内还是在全局范围内。 在ECMAScript 5严格模式下,将其分配给未声明的变量将引发错误。 1个
在这种情况下,当service.Test
函数被称为第二时间,全局值TestCallBack
正由在第二实例的引用,所述匿名函数替代service.Test
功能。 匿名TestCallBack
函数引用service.Test
函数的闭包2 。 闭包是一种特殊的对象,它结合了两件事:一个函数以及创建该函数的环境。 因此,由第一个实例调度的函数将其i
和resultsLocation
切换到service.Test
函数的第二个实例的关闭 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.