javascript - 使用 Controller 初始化 Angular 服务的正确方法

标签 javascript angularjs jquery-mobile

我来自静态类型的面向对象背景 (C#),并且一般来说是 Angular 和 Javascript 的新手。我正在尝试使用 Angular 和 JQueryMobile 构建一个应用程序,并且面临着服务行为不像单例那样的情况 - 即,即使它们已经在一个 Controller 中初始化一次,服务中的属性也没有存储任何状态传递到另一个 Controller 或服务时设置为。此外,当我尝试调试下面描述的代码时,我遇到了一些意外行为:

我的设置:

  • 我正在使用 JQueryMobile 单页模板,将应用程序的所有页面作为同一 html 页面上的 div,并且使用“href="#DivName”模式进行重定向
  • 应用程序的每个 div(页面)都有一个关联的 Controller 和服务
  • Controller 根据需要注入(inject)多个服务,并且注入(inject)的服务应保持它们在其他 Controller 中初始化的状态。
  • 我没有使用路由和模板 - 整个 html 都在一个页面中

  • 相关代码大纲如下:

    HTML:
    <div data-role="page" id="PageA" data-ng-controller="PageAController">      
    
    <!-- page content and UI elements-->    
    
    </div>
    
    
    <div data-role="page" id="PageB" data-ng-controller="PageBController">
    
    <!-- page content and UI elements-->    
    
    </div>
    

    服务:
    var App = angular.module('App', []);
    
    App.service('serviceA', function () {
    
        var propA;
    
        //objectX is an array of objects with each object containing a hashtable and some other properties 
    
        propA = [{},{}];  //hardcoded value for objectX gets returned properly
    
        return {
    
            initialize: function(objectX){          
    
                propA = objectX; // Dynamically initialized objectX value is returned as "undefined" by the getPropA function below
            },                 
    
            getPropA: function () {               
    
                return propA;
            }
        };
    });
    
    App.service('serviceB', function (serviceA) {
    
        var propB;
    
        return {
    
            initialize: function(){         
    
                propB = serviceA.getPropA();    //THIS DOES NOT WORK AS THE VALUE RETURNED IS UNDEFINED     
            },                 
    
            processPropB: function () {               
    
                //logic for processing of propB
            }
        };
    });
    

    Controller :
    App.controller('ControllerA', ['$scope', 'ServiceA',
    function ($scope, ServiceA) {    
    
        $scope.UITriggeredAction = function(){          
            ServiceA.initialize(objectX);
        };    
    
    }]);
    
    //This controller gets invoked at a later point during the user interaction where ServiceA is supposed to be initialised and injected
    
    
    App.controller('ControllerB', ['$scope', 'ServiceB', 'ServiceA',
    function ($scope, ServiceB, ServiceA,) {    
    
        var returnedPropA = ServiceA.getPropA(); //THIS RETURNS UNDEFINED TOO
    
        //process logic to use serviceB depending on valu of returnedPropA
    
    }]);
    

    问题:
  • 在上面的 serviceA 代码中,如果我通过在 return 块之前硬编码来初始化 propA 的值,则在执行 getPropA() 方法时确实会返回该值。请解释这是如何工作的。
  • 我还想知道在 Angular 中调用 javascript 代码的顺序——我的理解是,当相关页面加载到浏览器中时,Angular 运行时会调用相应的 Controller 函数,而 Controller 代码又会调用服务方法。但是如果我在不同的 Controller 和/或服务中有警报并加载页面,即使不应该调用页面或 Controller /服务,警报也会立即显示。更奇怪的是,当放置警报的实际 Controller 或服务方法确实被执行时,警报并没有被执行。似乎所有 Controller 都在页面加载时执行。

  • 请让我知道如何设置我的代码,以便我可以在不同的 Controller 中传递服务,而不会在执行期间的任何地方初始化或更新后丢失它们的状态。

    谢谢,
    尚塔努

    编辑:

    我认为答案就在我的第二个问题中。对我来说 - 代码执行的控制流不清楚。以下是我认为的问题:

    基本上,两个 angular Controller 都是在 angular 运行时在页面加载时执行的,而不是按照它们在应用程序中加载和使用的顺序执行的——尽管这可能只是 JQMobile 的事情。

    当对用户界面 Action 进行赋值操作时,服务中的相应变量设置成功。但是 angular 运行时不会重新评估所有 Controller 以确保新分配反射(reflect)在所有 Controller 上。

    所以另一个 Controller 继续返回它在初始化时设置的内容 - 未定义。

    但是,如果该变量是在页面加载本身时设置的 - 那就是在使用所需值进行初始化时返回的值,并且一切正常。

    根据要求,我还在下面创建了一个简单的 plunk 来显示上述要点和评论:
    http://plnkr.co/edit/yBOL0P3ycsoNzVrydaMs

    作为问题的解决方案,以下是我认为应该起作用的方法:
  • 以某种方式确保 Controller 仅在需要时初始化,而不是在页面加载时一次性初始化,以便初始化可以按照之前操作中设置的状态进行。我认为可以通过模板和路由来实现,这样 Controller 仅在所需的路由和模板被称为 foe 时才被调用。我不确定这是否是它的工作方式。
  • 第二个选项是在设置 Controller 中发布事件并在需要保持同步的任何地方订阅它们。这似乎是一种更好的方法。

  • 如果可行,我会确认并发布答案。

    请让我知道你的想法。

    抱歉,帖子太长了:)

    最佳答案

    我不知道这是否解决了问题,但我认为您正在实例化服务,就好像它是一个工厂。

    工厂返回并反对,就像您正在做的那样......

    但是服务应该使用“this”类型的语法:

    App.service('serviceA', function () {
       var somePrivateProperty;
       this.propA = [{},{}];      // public property
       this.initalize = function(objectX) { 
           this.propA = objectX
        }
       this.getPropA = function() { return this.propA }
       // although, your controller which Injects this service, 
       // could access propA directly without the getter
    
       var somePrivateMethod = function() {}
    
    
      });
    

    服务与工厂的示例:http://jsfiddle.net/thomporter/zjFp4/1/

    关于javascript - 使用 Controller 初始化 Angular 服务的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22460716/

    相关文章:

    javascript - 使用 AES 算法在 javascript 中加密并在 C# 中解密

    javascript - 传单 map 已移出 div 标签

    javascript - 如何在基于 angularjs 的应用程序中隐藏工具提示?

    jQuery 移动 : problem with submitting forms due to page transitions

    jquery-mobile - 在 Xamarin 解决方案中使用 jQuery Mobile 是否可行?

    javascript - TypeScript 和 this 关键字(SharePoint 框架和 Vue)

    javascript - 如何在 React.js 中将带有 jsx 的 html 转换为 jsx

    javascript - 如何在不更改缓存 list 的情况下使用 html 5 缓存 list 以编程方式更新页面服务器端?

    javascript - 从对象中删除元素时,它会从 React js 中的父元素中删除

    ruby-on-rails - Rails 应用程序的部分是 SPA (AngularJS) 或多个 SPA