多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > web前端 > htmlcss > AngularJS Providers 詳解

AngularJS Providers 詳解

來源:程序員人生   發布時間:2015-02-27 08:21:39 閱讀次數:5669次
??

供應者(Providersimage

Each web application you build is composed of objects that collaborate to get stuff done. These objects need to be instantiated and wired together for the app to work. In Angular apps most of these objects are instantiated and wired together automatically by the injector service.

你創建的任何 Web 利用都是1些相互依賴的對象組合。這些對象需要被實例化并被綁定在1起工作。在 Angular 利用中,這些對象通過注入器服務自動完成實例化和綁定。

The injector creates two types of objects, services and specialized objects.

注入器創建了兩種類型的對象,services(服務)和 specialized objects(特殊對象)。

Services are objects whose API is defined by the developer writing the service.

服務同等于對象,它的 API 由編寫服務的開發者定義。

Specialized objects conform to a specific Angular framework API. These objects are one of controllers, directives, filters or animations.

特殊對象服從1套專門的 Angular 框架 API。這些對象是控制器、指令、過濾器或動畫效果中的1個。

The injector needs to know how to create these objects. You tell it by registering a "recipe" for creating your object with the injector. There are five recipe types.

注入器需要知曉如何去創建這些對象。你通過注冊1個“recipe(配方)” 來告知注入器去創建你的對象。共有5種類型的配方。

The most verbose, but also the most comprehensive one is a Provider recipe. The remaining four recipe types ― Value, Factory, Service and Constant ― are just syntactic sugar on top of a Provider recipe.

最繁瑣,也是功能最全面的是 Provider recipe。剩下的4種類型――Value,Factory,Service 和 Constant ―― 僅僅是 Provider recipe 的語法糖。

Let's take a look at the different scenarios for creating and using services via various recipe types. We'll start with the simplest case possible where various places in your code need a shared string and we'll accomplish this via Value recipe.

接下來,我們看看如何在不同場景下通過不同的 recipe types 創建和使用 services 。我們將從最簡單的例子開始,通過 Value recipe在代碼中同享1個字符串。


 

Note: A Word on Modules

注意:模塊概要

 

In order for the injector to know how to create and wire together all of these objects, it needs a registry of "recipes". Each recipe has an identifier of the object and the description of how to create this object.

為了讓注入器知曉如何創建和綁定所有的對象,它需要1個"recipes"的注冊表。每一個 recipe 都有唯1的對象標識符和和何創建這個對象的描寫。

Each recipe belongs to an Angular module. An Angular module is a bag that holds one or more recipes. And since manually keeping track of module dependencies is no fun, a module can contain information about dependencies on other modules as well.

每一個 recipe 屬于1個 Angular 模塊。Angular 模塊是1個保存了1個或多個 recipes 的袋子。手動跟蹤模塊依賴關系明顯不是1個好方法,因此1個模塊也能夠包括依賴其它模塊的相干信息。

When an Angular application starts with a given application module, Angular creates a new instance of injector, which in turn creates a registry of recipes as a union of all recipes defined in the core "ng" module, application module and its dependencies. The injector then consults the recipe registry when it needs to create an object for your application.

1個 Angular 利用開始于1個給定的利用模塊時,Angular 會創建1個新的注入器實例,進而依照所有核心"ng"模塊、利用模塊和在它的依賴中統1定義的 recipes 來創建1個 recipes 的注冊表。然后,注入器通過查詢 recipes 注冊表來創建利用所需的對象。

 

 

變量方式(Value Recipe

Let's say that we want to have a very simple service called "clientId" that provides a string representing an authentication id used for some remote API. You would define it like this:

假定我們想要取得1個非常簡單的 service 叫做"clientId",它提供1個字符串用于表示某些遠程 API 的認證 id。你可以這樣去定義它:

var myApp = angular.module('myApp', []); 
myApp.value('clientId', 'a12345654321x');

Notice how we created an Angular module called myApp, and specified that this module definition contains a "recipe" for constructing the clientId service, which is a simple string in this case.

注意,我們創建1個名為 myApp 的 Angular 模塊,然后指定了1個包括構建 clientId service 的配方,這只是1個字符串的簡單例子。

And this is how you would display it via Angular's data-binding:

以下是如何通過 Angular數據綁定來顯示它:

myApp.controller('DemoController', ['clientId', function DemoController(clientId) { 
this.clientId = clientId; 
}]);

<html ng-app="myApp"> 
<body ng-controller="DemoController as demo"> 
Client ID: {{demo.clientId}} 
</body> 
</html>

In this example, we've used the Value recipe to define the value to provide when DemoController asks for the service with id "clientId".

在這個例子中,我們使用了 Value recipe 去定義這個 value,提供給 DemoController 要求這個服務的 id "clientId"。

On to more complex examples!

更復雜的例子!


 

工廠方式(Factory Recipe

The Value recipe is very simple to write, but lacks some important features we often need when creating services. Let's now look at the Value recipe's more powerful sibling, the Factory. The Factory recipe adds the following abilities:

這個 Value recipe 寫起來非常簡單,但缺少創建 service時常常用到的1些重要特點。現在讓我們看看 Value recipe 更強大的兄弟――Factory。Factory recipe 增加了以下能力:

ability to use other services (have dependencies)

能夠使用其它的 services(依賴)

service initialization

service 初始化

delayed/lazy initialization

延遲/怠惰初始化

The Factory recipe constructs a new service using a function with zero or more arguments (these are dependencies on other services). The return value of this function is the service instance created by this recipe.

Factory recipe通過1個包括有零個或多個參數(它所依賴的其它 services)的方法構造1個新的 service。這個方法的返回值是由 recipe 創建的這個服務的實例。

Note: All services in Angular are singletons. That means that the injector uses each recipe at most once to create the object. The injector then caches the reference for all future needs.

注意:Angular 中所有的服務都是單例模式。這意味著注入器創建這個對象時,僅使用1次recipe。然后注入器緩存所有將來需要的援用。

Since Factory is more powerful version of the Value recipe, you can construct the same service with it. Using our previous clientId Value recipe example, we can rewrite it as a Factory recipe like this:

由于 Factory 是Value recipe 更強大的版本,你可以構造和它1樣的服務。使用我們之前的 clientId Value recipe 的例子,可以采取 Factory recipe 這樣重寫:

myApp.factory('clientId', function clientIdFactory() { 
return 'a12345654321x'; 
});

But given that the token is just a string literal, sticking with the Value recipe is still more appropriate as it makes the code easier to follow.

但斟酌到令牌僅僅是1個字符串常量,使用 Value recipe 更恰當,也更容易于代碼的瀏覽。

Let's say, however, that we would also like to create a service that computes a token used for authentication against a remote API. This token will be called apiToken and will be computed based on the clientId value and a secret stored in the browser's local storage:

比如說,我們想創建1個用于計算遠程 API 認證令牌的服務。這個令牌將被稱做 apiToken,并計算基于 clientId 的值,然后加密存儲于閱讀器 Local Storage 中:

myApp.factory('apiToken', ['clientId', function apiTokenFactory(clientId) { 
var encrypt = function(data1, data2) { 
// NSA-proof encryption algorithm: 
return (data1 + ':' + data2).toUpperCase(); 
}; 
var secret = window.localStorage.getItem('myApp.secret'); 
var apiToken = encrypt(clientId, secret); 
return apiToken; 
}]);

In the code above, we see how the apiToken service is defined via the Factory recipe that depends on clientId service. The factory service then uses NSA-proof encryption to produce an authentication token.

在上面的代碼中,我們看到了如何通過工廠方法定義這個依賴于 clientId 服務的 apiToken 服務。這個工廠服務使用 NSA-proof 加密去產生1個認證令牌。

Note: It is best practice to name the factory functions as <serviceId>Factory (e.g. apiTokenFactory). While this naming convention is not required, it helps when navigating the code base or looking at stack traces in the debugger.

注意:工廠方法命名的最好實踐類似于<serviceId>Factory (e.g. apiTokenFactory)。雖然這類命名習慣不是必須的,但它有助于代碼庫導航或查看調試器的堆棧跟蹤。

Just like with Value recipe, Factory recipe can create a service of any type, whether it be a primitive, object literal, function, or even an instance of a custom type.

與 Value recipe 1樣,Factory recipe 能夠創建任何類型的服務,對象常量,方法,乃至1個自定義類型的實例。


 

 

服務方式(Service Recipe

JavaScript developers often use custom types to write object-oriented code. Let's explore how we could launch a unicorn into space via our unicornLauncher service which is an instance of a custom type:

JavaScript 開發者常常使用自定義的類型去編寫面向對象的代碼。讓我們探究如何通過 unicornLauncher 服務發射1個 unicorn(獨角獸)進入太空,這是1個自定義類型的實例:

function UnicornLauncher(apiToken) { 
this.launchedCount = 0; 
this.launch = function() { 
// make a request to the remote api and include the apiToken 
... 
this.launchedCount++; 
} 
}

We are now ready to launch unicorns, but notice that UnicornLauncher depends on our apiToken. We can satisfy this dependency on apiToken using the Factory recipe:

我們現在來準備發射 unicorn,但請注意 UnicornLauncher 依賴了我們的 apiToken。我們可使用 Factory recipe 來滿足這個 apiToken的依賴:

myApp.factory('unicornLauncher', ["apiToken", function(apiToken) { 
return new UnicornLauncher(apiToken); 
}]);

This is, however, exactly the use-case that Service recipe is the most suitable for.

就是這樣。不過,使用 Service recipe 才是最為恰當的例子。

The Service recipe produces a service just like the Value or Factory recipes, but it does so by invoking a constructor with the new operator. The constructor can take zero or more arguments, which represent dependencies needed by the instance of this type.

這個 Service recipe 產生1個類似于 Value 和 Factory recipes ,但它通過調用構造函數去履行 new 操作。這個構造函數可以接受零或多個參數,表示這個類型實例所需的依賴項。

Note: Service recipes follow a design pattern called constructor injection.

注意:Service recipes 的設計模式被稱之為構造函數注入。

Since we already have a constructor for our UnicornLauncher type, we can replace the Factory recipe above with a Service recipe like this:

由于我們已有了1個 UnicornLauncher 類型的構造函數,就可以夠像這樣去用 Service recipe 替換 Factory recipe:

myApp.service('unicornLauncher', ["apiToken", UnicornLauncher]);

Much simpler!

多么簡單!

Note: Yes, we have called one of our service recipes 'Service'. We regret this and know that we'll be somehow punished for our mis-deed. It's like we named one of our offspring 'Child'. Boy, that would mess with the teachers.

注意:是的,我們有1個被稱為“Service”的 service recipes。很遺憾我們將由于 mis-deed 而遭到報應。這就像是給我們某1個后代起名叫“小盆友”。這么弄會讓老師們困惑。

 

供應者方式(Provider Recipe

There are two more recipe types left to cover. They are both fairly specialized and are used infrequently. As already mentioned in the intro, the Provider recipe is the core recipe type and all the other recipe types are just syntactic sugar on top of it. It is the most verbose recipe with the most abilities, but for most services it's overkill.

還有兩個 recipe 類型。它們都相當特殊,很少使用。如前述,Provider recipe 是核心 recipe 類型,所有其他的配方類型只是基于它的語法糖。它是最詳細功能最多的 recipe,但對大多數服務來講,它是過剩的。

Provider recipe is syntactically defined as a custom type that implements a $get method. This method is a factory function just like the one we use in Factory recipe. In fact, if you define a Factory recipe, an empty Provider type with the $get method set to your factory function is automatically created under the hood.

Provider recipe 是語法定義為1個自定義類型,實現 $get 的方法。這個方法是1個工廠方法,就像我們在 Factory recipe 中使用的1樣。事實上,如果你定義1個 Factory recipe,鉤子會自動創建1個包括空 Provider 類型 $get 方法的工廠方法。

You should use the Provider recipe only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications.

只有當你希望1個利用程序配置的 API 必須在利用程序啟動之前被創建,你才應當使用 Provider recipe 。通常只關注可重用服務的行動可能在利用程序間略有不同。

Let's say that our unicornLauncher service is so awesome that many apps use it. By default the launcher shoots unicorns into space without any protective shielding. But on some planets the atmosphere is so thick that we must wrap every unicorn in tinfoil before sending it on its intergalactic trip, otherwise they would burn while passing through the atmosphere. It would then be great if we could configure the launcher to use the tinfoil shielding for each launch in apps that need it. We can make it configurable like so:

我們假定 unicornLauncher是個很不錯的服務,許多利用程序都在使用它。默許情況下,launcher 發射 unicorns 進入太空時沒有任何防護屏蔽。但某些行星的大氣層實在是太厚了,以致于我們在星際旅行發射之前,必須用錫紙包住每個 unicorns,否則它們將會在穿越大氣層時燒毀。如果我們可以依照利用程序的需要去為 launcher 的每次發射配置使用錫箔屏蔽罩,那就再好不過了。我們可做以下配置:

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); 
}]; 
});

To turn the tinfoil shielding on in our app, we need to create a config function via the module API and have theUnicornLauncherProvider injected into it:

為了在我們的利用程序中啟用錫紙屏蔽罩,我們需要通過模塊的 API 創建1個含有注入 UnicornLauncherProvider 的配置方法:

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

 

Notice that the unicorn provider is injected into the config function. This injection is done by a provider injector which is different from the regular instance injector, in that it instantiates and wires (injects) all provider instances only.

請注意 unicorn provider 被注入的配置方法,這類注入是通過 provider 的注入器完成的,不同于普通的實例注入器只是由 provider 實例進行實例化和綁定(注入)。

During application bootstrap, before Angular goes off creating all services, it configures and instantiates all providers. We call this the configuration phase of the application life-cycle. During this phase services aren't accessible because they haven't been created yet.

在利用程序啟動期間,Angular 創建的所有服務前,配置和實例化所有的 providers。我們稱之為利用程序生命周期中的配置階段。在此階段服務還不可用,由于它們還沒有被創建。

Once the configuration phase is over, interaction with providers is disallowed and the process of creating services starts. We call this part of the application life-cycle the run phase.

配置階段結束,providers 交互被制止,開始創建 services。我們稱這1階段為利用程序生命周期的運行階段。


 

 

常量方式(Constant Recipe

We've just learned how Angular splits the life-cycle into configuration phase and run phase and how you can provide configuration to your application via the config function. Since the config function runs in the configuration phase when no services are available, it doesn't have access even to simple value objects created via Value recipe.
我們已學會了如何辨別利用程序生命周期中的配置階段和運行階段,如何通過配置方法向您的利用程序提供配置。由于配置方法運行在配置階段,此時還沒有服務可用,因此它不能訪問任何對象,哪怕是通過 Value recipe 創建的 value 對象。

Since simple values, like url prefix, don't have dependencies or configuration, it is often handy to make them available in both the configuration and run phases. This is what the Constant recipe is for.

而簡單的值,比如 url 的前綴,沒有依賴或配置,需要在配置和運行階段皆可以使用。這就是 Constant recipe。

Let's say that our unicornLauncher service can stamp a unicorn with the planet name it's being launched from if this name was provided during the configuration phase. The planet name is application specific and is used also by various controllers during the runtime of the application. We can then define the planet name as a constant like this:

假定 unicornLauncher 服務可以標出 unicorn 發射自哪顆行星,而且這個行星的名字需要在配置階段提供。同時,星球的名字會由利用程序指定,并且被多個控制器在運行階段使用。

We can then define the planet name as a constant like this:

我們可以依照以下方式定義這個星球的名字為1個常量:

myApp.constant('planetName', 'Greasy Giant');

We could then configure the unicornLauncherProvider like this:

我們這樣可以配置 unicornLauncherProvider:

myApp.config(['unicornLauncherProvider', 'planetName', function(unicornLauncherProvider, planetName) { 
  unicornLauncherProvider.useTinfoilShielding(true); 
  unicornLauncherProvider.stampText(planetName); 
}]);

And since Constant recipe makes the value also available at runtime just like the Value recipe, we can also use it in our controller and template:

由于在運行階段,Constant recipe 創建的值和 value recipe 1樣,所以我們也能夠在控制器和模板中使用它:

myApp.controller('DemoController', ["clientId", "planetName", function DemoController(clientId,planetName) { 
this.clientId = clientId; 
this.planetName = planetName; 
}]);

<html ng-app="myApp"> 
<body ng-controller="DemoController as demo"> 
Client ID: {{demo.clientId}} 
<br> 
Planet Name: {{demo.planetName}} 
</body> 
</html>

 

 

特殊目的對象(Special Purpose Objects

Earlier we mentioned that we also have special purpose objects that are different from services. These objects extend the framework as plugins and therefore must implement interfaces specified by Angular. These interfaces are Controller, Directive, Filter and Animation.

如上所述,我還有不同于 services,用于特殊目的對象。這些擴大作為框架的插件,因此必須實現 Angular 指定的接口。這些接口是:控制器、指令、過濾器和動畫效果。

The instructions for the injector to create these special objects (with the exception of the Controller objects) use the Factory recipe behind the scenes.

舉例說明注入器創建特殊對象(控制器對象除外)使用 Factory recipe。

Let's take a look at how we would create a very simple component via the directive api that depends on the planetNameconstant we've just defined and displays the planet name, in our case: "Planet Name: Greasy Giant".

讓我們看1下如何通過指令 api 創建1個非常簡單的組件,取決于我們剛才 planetName 定義的常量和行星的名字,在我們的例子中:“行星名稱:Greasy Giant”(油膩偉人)。

Since the directives are registered via Factory recipe, we can use the same syntax as with factories.

自從通過工廠方法注冊指令以后,我們就能夠使用與 factory 相同的語法。

myApp.directive('myPlanet', ['planetName', function myPlanetDirectiveFactory(planetName) {
// directive definition object
return {
    restrict: 'E',
    scope: {},
    link: function($scope, $element) { $element.text('Planet: ' + planetName); }
}
}]);

We can then use the component like this:

然后,這樣使用組件:

<html ng-app="myApp">
<body>
<my-planet></my-planet>
</body>
</html>

Using Factory recipes you can also define Angular's filters and animations, but the controllers are a bit special. You create a controller as a custom type that declares its dependencies as arguments for its constructor function. This constructor is then registered with a module. Let's take a look at the DemoController, created in one of the early examples:

使用 Factory recipes,你還可以定義 Angular 的過濾器和動畫效果,但是控制器有些許特殊。創建1個控制器作為自定義類型,聲明包括作為其依賴項參數的構造函數。然后注冊這個構造函數到1個模塊。讓我們看看 DemoController 先前的例子:

myApp.controller('DemoController', ['clientId', function DemoController(clientId) {
this.clientId = clientId;
}]);

The DemoController is instantiated via its constructor every time the app needs an instance of DemoController (in our simple app it's just once). So unlike services, controllers are not singletons. The constructor is called with all the requested services, in our case the clientId service.

DemoController 是根據利用程序的需要,通過其構造函數實例化的(在我們的簡單利用中只有1次)。與服務不同,控制器其實不是單例的。構造函數被所有要求的服務調用,在我們的案例中是 clientId service。


 

 

結論(Conclusion

To wrap it up, let's summarize the most important points:

概括上述內容,讓我來總結1下最重要的幾點:

The injector uses recipes to create two types of objects: services and special purpose objects.

注入器通過使用 recipes 來創建兩種類型的對象:服務和特殊目的對象。

There are five recipe types that define how to create objects: Value, Factory, Service, Provider and Constant.

1共有5種類型的 recipe 用于定義如何創建對象:變量、工廠、服務、供應者和常量。

Factory and Service are the most commonly used recipes. The only difference between them is that Service recipe works better for objects of custom type, while Factory can produce JavaScript primitives and functions.

工廠和服務是最經常使用的方式。二者唯一的不同是服務方式對自定義類型對象效果更好,而工廠方式可以提供 JavaScript 基元和方法。

The Provider recipe is the core recipe type and all the other ones are just syntactic sugar on it.

供應者方式是核心方式,所有其它方式都是它的語法糖。

Provider is the most complex recipe type. You don't need it unless you are building a reusable piece of code that needs global configuration.

供應者是最復雜的方式類型。除非你正在構建1段需要全局配置的可重用代碼,否則不要使用它。

All special purpose objects except for Controller are defined via Factory recipes.

所有特殊目的對象都通過工廠方式來定義,除控制器。

Features / Recipe type

Factory

Service

Value

Constant

Provider

can have dependencies
支持依賴注入

yes

yes

no

no

yes

uses type friendly injection
使用友好的注入方式

no

yes

yes*

yes*

no

object available in config phase
配置階段可用

no

no

no

yes

yes**

can create functions/primitives
可以創建方法/基元

yes

no

yes

yes

yes

* at the cost of eager initialization by using new operator directly

以使用 new 操作符初始化為代價。

** the service object is not available during the config phase, but the provider instance is (see the unicornLauncherProviderexample above).

** 服務對象在配置階段不可用,除供應者實例(參見上面的 unicornLauncherProvider 示例)。

 

原文鏈接: https://docs.angularjs.org/guide/providers

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 一区二区三区鲁丝不卡麻豆 | 国产一级做a爱免费视频 | 午夜免费啪在线观看视频网站 | 国产欧美日韩免费一区二区 | 性欧美欧美 | 国产成+人欧美+综合在线观看 | 亚洲精品一二三四区 | 伊人精品视频在线 | 国产精品大白天新婚身材 | 国产福利视频一区二区三区 | 爱爱www在线观看视频高清 | 国产欧美久久一区二区 | 欧美日韩亚洲视频 | 亚洲jizzjizz中文在线播放 | 国产精品亚洲欧美一级久久精品 | 色老久久精品偷偷鲁一区 | 久久精品国产主播一区二区 | www在线观看免费 | 一级片 720p| 国产成人精品视频 | 黄色录像大片毛片aa | 日本一区二区三区四区在线观看 | 亚洲国产精品久久久久久 | 国产一区二区在线免费观看 | 亚洲日韩欧美综合 | 亚欧综合 | 国产成人高清 | 国内免费自拍视频 | 亚洲a色 | 亚洲国产一级毛片 | 亚洲伊人成综合成人网 | 青草超级碰碰在线视频 | 亚洲国产精品第一区二区三区 | 亚洲资源站资源网在线 | 国产一区二区三区欧美精品 | 另类图片综合 | 今天免费中文字幕视频 | 国产美女啪啪 | 久久综合九色综合欧洲色 | 国产一区二区三区在线观看精品 | 欧美又粗又长又爽做受 |