仍然对angularjs服务和工厂感到困惑

我已经阅读了几个关于angularjs服务和工厂的主题。 我明白,服务是单身人士,工厂返回对象的实例。 但我仍然不太明白如何使用它们。 我的应用是一个简单的社交网络。 使用该应用程序的人需要登录,然后他们才能查看其他成员并向他们发送消息。

我的理想设计是:

  • 创建一个成员对象来表示我的服务的任意成员。 每当'list'或'get'操作返回数据时,它都会被封装在这个成员中,所以我可以调用它的实用方法。 我会用这个工厂。
  • 当用户登录到应用程序时,创建一个成员来表示他们(包含他们的用户ID和身份验证令牌以用于未来经过身份验证的请求)。 这必须可供其他作用域使用,因此可以附加到$ rootScope上,也可以是返回为经过身份验证的用户量身定制的Member的实例的MemberService。
  • 我创建了以下内容:

    angular.module('myapp.models', [])
    .factory('Member', ['$log', 'DataService', '$http', 'Restangular',
        function($log, DataService, $http, Restangular) {
            return {
                user_id: null,
                first_name: null,
                last_name: null,
    
                authenticate: function(username, password, loginSuccessHandler, loginErrorHandler) {
                    $log.debug("inside Member.authenticate");
    
                    var authSuccessHandler = function(data, status, headers, config) {
                        $http.defaults.headers.common.Authorization = 'Basic ' + btoa(data._id + ':' + data.token);
                        var token = btoa(data._id + ':' + data.token);
                        user_id = data._id;       // attach this to the rootScope? Needs to be
                                                  // globally accessible (or even this whole object)
                        Restangular.setDefaultHeaders({'Authorization': 'Basic ' + token});
                        $log.debug("Auth successful, token stored " + token);
                        loginSuccessHandler();
                    };
    
                    DataService.authenticate(username, password, authSuccessHandler, authErrorHandler);
                },
          ...
    

    我怎样才能实例化它,并使其可用于其他范围(例如,在其他范围我会知道登录的用户的ID)?

    另外,当我解析一列成员时,我怎么能实例化这个对象? 例如,如果我有一个对象{first_name: "John", last_name: "Smith"}我怎么能从这个工厂获得一个成员对象,并设置这些属性?


    factoryservice都是provider抽象。

    这是angular用来实例化新提供者的方法:

    function provider(name, provider_) {
        if (isFunction(provider_) || isArray(provider_)) {
            provider_ = providerInjector.instantiate(provider_);
        }
        if (!provider_.$get) {
            throw Error('Provider ' + name + ' must define $get factory method.');
        }
        return providerCache[name + providerSuffix] = provider_;
    }
    

    第一部分在角度应用程序加载时实例化一个新的(单例)对象。 $get方法用作新对象的构造函数。 这是一个provider的实例化可能看起来像(从角度的文档):

    myApp.provider('unicornLauncher', function UnicornLauncherProvider() {
      var useTinfoilShielding = false;
    
      this.useTinfoilShielding = function(value) {
        useTinfoilShielding = !!value;
      };
    
      this.$get = ["apiToken", function unicornLauncherFactory(apiToken) {
    
        // let's assume that the UnicornLauncher constructor was also changed to
        // accept and use the useTinfoilShielding argument
        return new UnicornLauncher(apiToken, useTinfoilShielding);
      }];
    });
    

    以下是配置提供者的方法。 在module.config()块中,与稍后我们将提供者注入到控制器/指令/服务时不同,我们获取单例,而不是$get方法的返回值。

    myApp.config(["unicornLauncherProvider", function(unicornLauncherProvider) {
      unicornLauncherProvider.useTinfoilShielding(true);
    }]);
    

    然后,无论何时注入并调用unicornLauncher$get方法中的内容都会被调用,并且您将获得一个带有提供的配置的新UnicornLauncher ,在这种情况下, useTinfoilShielding = true

    正如你所看到的,提供者有两部分。 首先,它是一个单例,在角度加载时实例化和配置,并推送到providerCache ,以便您可以在整个应用程序中使用它。 它还有一个用于实例化新对象的$get方法。

    你可以这样看待它:单身人士将它的属性和方法作为你在加载应用时设置的设置和数据,然后你可以创建使用这些设置和数据的新对象。

    如果您为其他人创建了一个模块供其使用,那么需要单独修改每个应用程序的选项,这就是您将要这样做的方式。 您可以将提供程序注入您的应用程序,对其进行配置,然后根据需要随时提供对象,并使用我们在配置提供程序时设置的预设。

    然后我们有服务工厂 。 这些实际上是对provider抽象。 以下是角度用于启动factory

    function factory(name, factoryFn) {
        return provider(name, { $get: factoryFn });
    }
    

    它只是一个provider ,而不是返回一个包含我们所看到的所有属性的对象,它只返回一个带有$get方法的对象,并且没有像provider那样的其他任何可变部分。

    这是service的功能:

    function service(name, constructor) {
        return factory(name, ['$injector', function($injector) {
            return $injector.instantiate(constructor);
        }]);
    }
    

    这里我们有一个工厂,它的$get方法使用提供的构造函数返回一个由angular实例化的单例。 所以你有一个你可以在整个应用程序中使用的单例,你可以在任何地方使用它的方法。 你可以在一个地方设置它的属性,并看到你在应用程序的其他地方设置的相同值,因为无论你注入哪个对象,它都是相同的单例对象。

    总结

    主要区别在于service是一个对象,它是在您声明服务时由您提供的构造函数创建的,而factory仅仅是一个可用于创建新对象的函数,就像您在本地JavaScript中一样。

    希望有助于了解factoryservice


    回到你的问题。

    在你的情况下,你有一个你想用来为每个成员创建一个新对象的工厂。 在注册Member的控制器中,您可以简单地执行以下操作:

    var data = {first_name: "John", last_name: "Smith"} 
    var member = new Member(data);
    

    对工厂进行小改动:

    .factory('Member', ['$log', 'DataService', '$http', 'Restangular',
        function($log, DataService, $http, Restangular) {
            return function(data) {
            //construct the object
            }
    ])
    

    对工厂的new调用(作为构造函数注入)将返回一个新的,唯一的对象,与JS中的其他对象一样构造。 你可以随心所欲地做任何事情。 您可以将其保留在控制器, $rootScope中或保存成员和其他相关数据和功能的服务中。 然后,您可以在整个应用程序中随时随地注入该服务。


    我只想说服务工厂以及提供者都是单身人士。

    其余的检查这些答案:AngularJS:服务vs提供者vs工厂

    链接地址: http://www.djcxy.com/p/13631.html

    上一篇: Still confused about angularjs services and factories

    下一篇: Some problems about DI in angular.js