gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-11-01 05:11:52 25 4
gpt4 key购买 nike

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

我理想的设计是:

  1. 创建一个成员对象来表示我的服务的任意成员。每当“列表”或“获取”操作返回数据时,它都会被包装在这个成员中,这样我就可以调用它的实用方法。我会为此使用工厂。
  2. 当用户登录到应用程序时,创建一个成员来代表他们(包含他们的用户 ID 和授权 token 以供将来经过身份验证的请求使用)。这必须对其他范围可用,因此可以附加到 $rootScope,或者是返回为经过身份验证的用户定制的成员实例的 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"} 我如何从这个工厂获得一个 Member 对象并设置了这些属性?

最佳答案

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_;
}

第一部分在 Angular 应用程序加载时实例化一个新的(单例)对象。 $get 方法用作新对象的构造函数。这就是 provider 的实例化可能的样子(来自 angular 的文档):

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() block 中,与我们稍后将提供程序注入(inject) Controller /指令/服务时不同,我们得到的是单例,而不是 $get< 的返回值 方法。

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

然后,每当您注入(inject)并调用 unicornLauncher 时,$get 方法中的内容将被调用,您将获得一个新的 UnicornLauncher提供的配置,useTinfoilShielding = true 在这种情况下。

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

您可以这样看:单例将其属性和方法作为您在加载应用程序时设置的设置和数据,然后您可以创建使用这些设置和数据的新对象。

如果您创建一个供其他人使用的模块,则需要针对每个应用程序单独修改选项,这就是您的做法。您可以将提供程序注入(inject)您的应用程序,对其进行配置,然后根据需要使用我们在配置提供程序时设置的预设来分发对象。

然后我们有服务工厂。这些实际上是对 provider 的抽象。这是 Angular 用来启动 factory 的函数:

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

它只是一个提供者,但不是返回一个具有我们看到的所有这些属性的对象,它返回一个只有一个$get 方法的对象并且没有任何其他可变部分,如 provider

这是服务的函数:

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

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

总结:

主要区别在于 service 是一个对象,由 angular 从你在声明服务时给它的构造函数创建,而 factory 只是一个函数,你可以用来创建新对象,就像在原生 JavaScript 中一样。

希望对理解factoryservice有帮助。


回到你的问题。

在你的例子中,你有一个工厂,你想用它为每个成员创建一个新对象。在注入(inject) Member 的 Controller 中,您可以简单地执行以下操作:

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 调用(作为构造函数注入(inject))将返回一个新的、唯一的对象,其构造与 JS 中的任何其他对象一样。你可以用它做任何你想做的事。您可以将其保留在 Controller 中、$rootScope 中,或者保留在包含成员和其他相关数据和函数的服务中。然后,您可以在整个应用程序的任何位置注入(inject)该服务。

关于javascript - 仍然对 angularjs 服务和工厂感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23034120/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com