繁体   English   中英

AngularJS具有一项服务的多个控制器:异步错误

[英]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) {

PLNKR上演示


因此,为了澄清一下,即使将函数声明为var,也可以将其置于全局范围内?

错误是将值设置为未声明的变量。

在执行赋值时,将值分配给未声明的变量会隐式地将其创建为全局变量 (它成为全局对象的属性)。 已声明和未声明的变量之间的区别是:

  1. 声明的变量被约束在声明它们的执行上下文中。 未声明的变量始终是全局变量。

  2. 在执行任何代码之前创建声明的变量。 在执行分配给它们的代码之前,未声明的变量不存在。

  3. 声明的变量是其执行上下文(函数或全局)的不可配置属性。 未声明的变量是可配置的(例如可以删除)。

由于这三个差异,声明变量失败很可能导致意外结果。 因此,建议始终声明变量,而不管它们是在函数范围内还是在全局范围内。 在ECMAScript 5严格模式下,将其分配给未声明的变量将引发错误。 1个

在这种情况下,当service.Test函数被称为第二时间,全局值TestCallBack正由在第二实例的引用,所述匿名函数替代service.Test功能。 匿名TestCallBack函数引用service.Test函数的闭包2 闭包是一种特殊的对象,它结合了两件事:一个函数以及创建该函数的环境。 因此,由第一个实例调度的函数将其iresultsLocation切换到service.Test函数的第二个实例的关闭

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM