RSS

Angular $provide Services

10 פבר

Angular $provide Services

 

clip_image001

אחת השאלות השכיחות ביותר זה מה הבדל בין provider, factory ו- service? נתחיל ממה משותף לכולם.

1.     כולם שירותים שהם Singletons שאמורים לבצע משימה מסוימת.

2.     השירותים לא נוצרים אם לא צריך אותם ( Instantiated lazily ).

 

Provider

Provider הוא השרות המרכזי ביותר של אנגולר ולמעשה כל האחרים הם עטיפות שלו. Provider הוא הכי מורכב כי הוא בנוי משתי שכבות של מתודות שיוצרות אותו.

1.      רישום – אובייקט Module חושף מתודה provider שמקבלת 2 ארגומנטים, הראשון שם ה-provider כ-string והשני פונקציה שמחזירה אובייקט עם $get, או רק אובייקט עם $get, ללא פונקציה.

1.      Angular.module(‘myApp’, [])

2.        .provider(‘myProvider’, function($logProvider) {

3.           …

4.           return {        

5.               

6.                $get: function factory($log) {            

7.                          …

8.                      }

9.               };

10.        });

קוד 1: רישום של provider בשם myProvider.

בקוד אני רושם את "myProvider" עם פונקציה שמחזירה אובייקט עם $get. משתמשים בפונקציה כאשר רוצים ליצור את האובייקט עם $get עם ערכים דינמיים, אם האובייקט לא מכיל ערכים דינמיים אפשר פשוט לרשום את האובייקט ולא צריך את הפונקציה שמייצרת אותו. הפונקציה גם יכולה לקבל Providers אחרים כמו למשל $logProvider, אך צריך לזכור שבשלב ה-config אפשר לשנות לכם את הערכים של $logProvider.

הקוד של המתודה provider בתוך הקובץ של אנגולר מראה את מה שאמרנו.

1.  function provider(name, provider_) {

2.      if (isFunction(provider_) || isArray(provider_)) {

3.          provider_ = providerInjector.instantiate(provider_);

4.      }

5.      if (!provider_.$get) {

6.          throw Error(…'must define $get factory method.');

7.      }

8.      return providerCache[name + providerSuffix] = provider_;

9.  }

קוד 2: הפונקציה provider.

שורות 2-4 בודקות אם רשמנו פונקציה ואם כן אז מפעילים אותה. שורות 5-7 בודקות שהתשובה של הפונקציה או אם רשמנו אובייקט יש לו את $get , אם לא זורקים טעות. שורה 8 מאחסנת את האובייקט עם ה-$get בזיכרון תחת השם “name+providerSuffix” (במקרה שלנו “myProviderProvider”).

 

2.      module.config – בשלב זה של עליית המודול אנחנו יכולים לקבל את האובייקט שנוצר בשלב הרישום. השם של האובייקט הוא [‘myProvider’+’Provider’]. (providerSuffix שווה”Provider” )

10.app.config(function (myProviderProvider) {

11.               myProviderProvider.isTrue = true;

12.   });

קוד 3: שינוי ערך באובייקט שמכיל את $get לפני שקוראים לפונקציה $get.

שלב ה-config מאפשר לנו לשנות את האובייקט לפני שהאנגולר יפעיל את הפונקציה שב-$get ומה שהפונקציה מחזירה זה ה-provider  שנקבל מעתה ואילך.

3. factory – אנגולר מפעיל את הפונקציה $get אחרי שלב ה-config בשלב זה כל השירותים זמינים ולכן אפשר לדרוש כל שרות שאנחנו רוצים. בדוגמא שלנו ( קוד 1 ) אנחנו מבקשים את $log.

4. run – בשלב זה ה-provider זמין לנו ולכל קוד אחר כמו ה-controller ו-directive.

clip_image003

המלבנים השחורים זה קוד שאנחנו כותבים ורושמים אותם לאנגולר. המלבן האדום אין לנו שליטה עליו.

מה היתרונות של provider?

כתיבת provider מאפשר לנו להשפיעה על תהליך היצור שלו בשלב ה-config לפני שהאנגולר מריץ את הפונקציה של $get. בשלב ה-run מקבלים את התשובה מפונקצית ה-$get.

דוגמא מלאה:

1.  angular.module('myApp', [])

2.    .provider('myPro', function() {

3.       return {        

4.            isTrue: false,        

5.            $get: function factory($log) {            

6.                  var self = this;            

7.                  return function c(msg) {

8.                        $log.debug(msg + " isTrue: " + self.isTrue);

9.                  };

10.         }

11.     };

12.    });

קוד 4 : דוגמא מלאה.

בשלב ה-config אנחנו רוצים לשנות את הערך של isTrue ל-true, ראה קוד 3.

סוד קטן:

רישום ה-Provider לא שייך ל-Module אלה $provide.

1.  angular.module('myModule', [], function ($provide) {

2.      $provide.provider('myProvider', function () {

3.        

4.      });

5.  });

 

factory

factory זה הפונקציה $get של ה-provider. הסיבה שיצרו factory פונקציה זה כדי לחסוך לכם את הכתיבה הבאה:

1.  Angular.module('myApp', [])

2.      .provider('myProvider', { $get: factoryFn });

 

אם נסתכל לתוך הקוד של פונקציה factory נראה שהוא פשוט חוסך לנו את הכתיבה הזאת.

1.  function factory(name, factoryFn) {

2.      return provider(name, { $get: factoryFn });

3.  }

 

כלומר שאנחנו עובדים עם הפונקציה  factory בשלב ה-config אנחנו נקבל אובייקט עם $get בלבד. ( לא לשכוח שכדי לקבל את האוביקט בשלב ה-config אנחנו צריכים לבקש [‘name+’Provider’], ה-name זה שם ה-factory עכשיו.

 

 

Service

Service זה factory כלומר provider. במבט על הקוד של אנגולר אנחנו מבינים ש-service זה פונקציה constructor ולכן צריך לקורא לה עם new.

1.  function service(name, constructor) {

2.      return factory(name, ['$injector', function ($injector) {

3.          // instantiated with the new operator

4.          return $injector.instantiate(constructor);

5.      }]);

6.  }

 

תרגום הקוד הזה ל-provider יראה כך:

1.  function service(name, constructor) {

2.      return provider(name, { $get: ['$injector', function ($injector) {

3.          // instantiated with the new operator

4.          return $injector.instantiate(constructor);

5.      }]

6.    });

7.  }

 

Decorator

ה-decorator מאפשר לנו לעטוף כל שרות בפונקציה שלנו. בדוגמא שלפנינו אני מוסיף ל-$log פונקציה warn שקוראת למעשה לפונקציה error. הארגומנט $delegate מיצייג את השרות שאני רוצה לעטוף ושאר הארגומנטים הם שירותים אחרים שאני יכול לבקש.

1.  $provide.decorator('$log', function ($delegate, $http) {

2.       $delegate.warn = $delegate.error;

3.       return $delegate;

4.  });

 

ה-decorator יוצר אחרי הפעלת הפונקציה $get. מכאן נובע שמשלב ה-run ואלה אני מקבל את העטיפה של השרות ולא את השרות המקורי.

clip_image005

 

סיכום:

אנגולר "מביא לשולחן" תמיכה מובנית ב-DI, עם יכולות לכתוב ולרשום את השירותים שאנחנו רוצים שיהיו זמינים להזרקה ע"פ ביקוש. לא לשכוח שהשירותים הם Singleton. אנגולר מאפשר לנו להשתמש במספר מתודות שונות כדי לרשום את השרות שלנו אך למעשה כולם הם עטיפות לפונקציה provider.

מודעות פרסומת
 
3 תגובות

פורסם ע"י ב- פברואר 10, 2014 ב- AngularJS, Uncategorized

 

3 תגובות ל-“Angular $provide Services

  1. רונן

    פברואר 11, 2014 at 3:11 am

    מעולה. קצר פשוט ולעניין. תודה אייל.

     

כתיבת תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s

 
%d בלוגרים אהבו את זה: