標籤:http io os 使用 java ar strong for 資料
AngularJS之Factory vs Service vs Provider
來源:開源中國社區
作者:oschina
當你初試 Angular 時,很自然地就會往 controller 和 scope 裡堆滿不必要的邏輯。一定要早點意識到,controller 這一層應該很薄;也就是說,應用裡大部分的商務邏輯和持久化資料都應該放在 service 裡。我每天都會在 Stack Overflow 上看到幾個同類的問題,關於如何在 controller 裡儲存持久化資料。這就不是 controller 該乾的事。出於記憶體效能的考慮,controller 只在需要的時候才會初始化,一旦不需要就會被拋棄。因此,每次當你切換或重新整理頁面的時候,Angular 會清空當前的 controller。與此同時,service 可以用來永久儲存應用的資料,並且這些資料可以在不同的 controller 之間使用。 Angular 提供了3種方法來建立並註冊我們自己的 service。
Factory
Service
Provider
|
如果你是“太長的不看” 1) 用 Factory 就是建立一個對象,為它添加屬性,然後把這個對象返回出來。你把 service 傳進 controller 之後,在 controller 裡這個對象裡的屬性就可以通過 factory 使用了。 2) Service 是用"new"關鍵字執行個體化的。因此,你應該給"this"添加屬性,然後 service 返回"this"。你把 service 傳進 controller 之後,在controller裡 "this" 上的屬性就可以通過 service 來使用了。 3) Providers 是唯一一種你可以傳進 .config() 函數的 service。當你想要在 service 對象啟用之前,先進行模組範圍的配置,那就應該用 provider。 |
詳細解釋(對於不是“太長不看”的讀者) 為了準確表現出 Factory、Service 和 Provider 之間的差別,下面我們用 3 種不同的方式來構建同一個服務。這個服務會用到 iTunes API 以及使用 $q 的 promise。 1) Factory Factory 是建立和佈建服務最常見的方式。除了“快速探索”之外,其實沒有什麼要補充的。只需建立一個對象,為它添加屬性,然後返回這個對象就可以了。當你把 factory 傳進 controller 中,對象的這些屬性就可以通過 factory 訪問。更詳細的例子如下: 首先建立一個對象,然後返回這個對象,如下。 現在如果我們把"myFactory"傳進 controller 裡,附加在 "service" 上的任何屬性都可以訪問到了。 |
現在讓我們向回呼函數中添加一些“private” 變數。當然 controller中是無法直接存取這些變數的,不過我們最終還是會在“service”中設定setter和個getter 方法,以便必要時修改這些“private”變數。 你可能注意到了,我們沒有將變數/函數加到“service”中。我們只是簡單的建立他們以便之後的使用和修改。
baseUrl 是iTunes API要求的根URL
_artist 是我們想要尋找的藝術家
_finalUrl 是最終的許可權定URL,即我們調用iTunes的入口
makeUrl 是一個建立並返回友好的iTunesURL的函數
既然我們的幫手/私人變數和函數放在的合適的位置,那麼讓我們向“service”對象中添加一些屬性。無論我們向”service“中添加什麼, 我們都能在任意一個我們傳遞進‘myFactory’ 的controller中使用。 |
我們來建立setArtist和getArtist方法來簡單的返回或設定artist。同樣建立一個方法使用我們建立的URL來調用iTunes API。這個方法將返回一個從iTunes API擷取資料後便會滿足的promise。如果你對Angular的promise接觸不多,我強烈推薦你深入的學習一下它。
setArtist 接受一個artist並且允許你設定artist
getArtist 返回artist
callItunes 首先調用makeUrl()方法以便構建$http請求使用的URL。然後它會設定promise對象,讓$http請求我們最終的URL, 再然後呢,因為$http返回一個promise,所以我們可以在請求後調用.success或.error。最後我們可以通過iTunes的資料來解析我們的promise,或者直接‘There was an error’來拒絕它。
|
現在我們的factory完成了。我們可以將"myFactory"注入到任意controller中了,然後就可以調用我們添加到service對象中的方法了(setArtist,getArtist,和callItunes)。 在上面的controller中,我們注入了‘myFactory’ service對象。然後我們設定$scope 對象的屬性。上面唯一棘手的代碼是處理promise。因為callItunes返回一個promise對象,一旦我們的promise滿足了,我們可以調用.then()方法以及設定$scope.data.artistData。你會注意到我們的controller是非常的“瘦”。因為我們所有的邏輯和持久化資料都存放在了service中而不是controller中。 |
2) Service 當我們建立一個Service時,我們所知道的最重要事可能就是Service通過new關鍵字執行個體化對象。這應該可以使熟悉JavaScript的人瞭解到了這段代碼的作用。但對於那些JS背景有限,或者不太熟悉new關鍵字的作用的人來說可能有點困難。那就讓我們來重溫一下JavaScript的準系統,以便協助我們瞭解Service究竟做了什麼。 讓我們先定義一個函數,然後通過new關鍵字來調用它,看看當解譯器遇到了new關鍵字的時候做了些什麼工作,以便協助我們瞭解使用new關鍵字來執行個體化一個函數時究竟有什麼變化。這個的最終結果應該和Service是一樣的。 |
首先,讓我們定義一個構造器。 這個一個典型的JavaScript式的構造方法。現在,只要我們使用new關鍵字來調用Person函數,就會將‘this‘關鍵字綁定到新建立的對象上。 接下來,讓我們給Person的prototype對象添加一個方法,這個方法對所有Person ‘類’的執行個體都是可用的。 現在,由於我們往prototype上添加了一個sayName方法,所以所有的Person執行個體都可以調用這個方法,並且輸出對應執行個體的name值。 既然我們已經有了一個Person的構造器,並在在其prototype上定義了一個sayName方法,那就讓我們去建立一個Person的執行個體,並調用這個sayName方法。 接下來,我們把建立Person構造器、往其prototype上添加方法、建立一個Person執行個體,並調用sayName方法的代碼寫在一塊,如下所示: |
現在,讓我們看一下當我們在JavaScript中使用new關鍵字的時候究竟發生了什麼。首先你應該已經注意到的是,當我們在例子中使用了new關鍵字之後,我們可以通過‘tyler‘來調用方法(sayName),看上去好像tyler是一個對象——那是因為它確實成了一個對象。所以,我們知道的第一件事就是我們的Person構造器返回了一個對象(object)。其次,我們知道,由於我們的sayName方法是定義在Person的prototype上,而不是直接定義在Person的執行個體上的,所以Person函數返回的對象(tyler)一定是由於未找到sayName方法,進而去prototype尋找sayName方法的。用更通俗的話來說,當我們調用tyler.sayName()時,JS解譯器說,“好吧,我先去我們剛建立的‘tyler‘對象上尋找sayName方法,然後調用它。等一下,我沒有在它上面找到sayName方法——我只看到了name和age,那讓我去prototype找一下吧。沒錯,它在prototype上,那就讓我調用它吧”。 下面的代碼示範了在JavaScript中使用new關鍵之後所做的事。它是上面這一段文字的一個基本的程式碼範例。我已經把從JS解譯器的角度來看整個過程的代碼寫在了注釋裡。 |
現在,既然我們瞭解了在JavaScript中new關鍵字是如何工作的,那麼在Angular中建立一個Service也應該變得容易理解了。 在建立一個Service時,需要理解的最重要的一件事就是我們使用new關鍵字去執行個體化Service對象。結合我們從上面的例子所瞭解到的知識,你應該已經意識到你可以將一些屬性和方法直接添加到this上,之後,在建立Service對象時,this會被作為傳回值返回。讓我們來看一下這種工作方式。 我們不用像之前Factory中的例子那樣建立一個對象,然後返回這個對象。因為我們使用了new關鍵字來調用,解譯器會建立一個對象,並關聯它的prototype對象,然後將該對象返回,而不用我們去做這些工作。 |
首先,讓我們建立我們的私人輔助函數。它應該看起來和我們在factory中所作的工作很類似。由於我已經在factory的例子中解釋過每一行代碼的含義了,所以我不會在這裡多作解釋,如有疑惑,請再次回味一下factory的例子。 接下來,我們將要把可以從控制器中訪問的方法添加到‘this’上。 現在,和使用factory一樣,所有將myService作為參數傳入的控制器都可以訪問到setArtist, getArtist, 和callItunes方法。下面是傳入了myService的控制器(基本上和factory的控制器一樣)。
正如我之前提到的那樣,一旦你瞭解了new關鍵字的作用,你就會知道在Angular中,Services和Factories幾乎一樣。 |
3) Provider 要記住的關於Provider的最重要的事情是,它們是你可以傳遞到應用程式的app.config部分唯一的服務。如果你需要在你的服務物件可以在你的應用程式之外任何地方都可用之前改變它的某些部分,這是非常重要的。雖然Services/Factories很相似,但也有一些差異,我們將會討論它們。 首先,我們用與我們建立Service 和 Factory類似的方式來建立我們的Provider。下面的變數是我們的‘私人‘和協助工具功能。 *同樣地,如果上面的代碼的任何部分令你糾結,請看下 Factory 部分,在那裡我更詳細地解釋了這些代碼的作用。 |
必須要注意的一點是只有這些變數和函數是可以在我們的app.config函數中訪問的。這曾一度使我感到困惑,所以你最好也要知道這點不同之處。你可以把Provider想象成由兩部分組成。第一部分的變數和函數是可以在app.config函數中訪問的,因此你可以在它們被其他地方訪問到之前來修改它們(如上所示)。第二部分(如下所示) 的變數和函數是可以在任何傳入了’myProvider‘的控制器中進行訪問的。 當你使用Provider建立一個service時,唯一的可以在你的控制器中訪問的屬性和方法是通過$get()函數返回內容。下面的代碼將$get方法寫在了’this‘(最終會被函數返回)上。現在,$get函數會返回所有我們希望在控制器中進行訪問的方法和屬性。下面是程式碼範例: |
現在,Provider的完整代碼如下所示: 現在,與我們的Factory和Service類似,setArtist, getArtist, 和callItunes可以在任何一個傳入了 myProvider 的控制器中訪問。下面是myProvider的控制器(幾乎和我們Factory/Service中的控制器一樣)。 正如前面提到的那樣,使用Provider建立一個service的獨特之處是,你可以在Provider對象傳遞到應用程式的其他部分之前在app.config函數對其進行修改。讓我們來看一個對應的例子。 |
現在你可以明白‘thingFromConfig’是怎麼樣地在我們的provider中是Null 字元串,而當它出現在DOM中時,它將是‘This sentence was set…’。 謝謝您的閱讀,我希望這有助於你能辨別在Angular中Factory, Service, 和 Provider之間的差異。 *要查看完整的程式碼範例,看看運行中的代碼,可以自由地fork我的repo:https://github.com/tylermcginnis33/AngularService |
本文轉自:開源中國社區 [http://www.oschina.net]
本文標題:AngularJS 之 Factory vs Service vs Provider
本文地址:http://www.oschina.net/translate/angularjs-factory-vs-service-vs-provider
參與翻譯:中獎啦, 戴倉薯, GoodLoser, 趙亮-碧海情天
英文原文:AngularJS: Factory vs Service vs Provider
AngularJS之Factory vs Service vs Provider