למתחילים, האם מישהו יכול להסביר בבירור את ההבדל בין שירות, מפעל לספק ב- AngularJS?


תשובה 1:

AngularJS: ההבדל בין שירות מול ספק מול מפעל

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

אם אתה חושב שהם דומים - אתה צודק. הם דומים מאוד. למעשה, כולם אותו הדבר.

כולם ספקים. המפעל והשירות הם רק מקרים מיוחדים של הספק, אבל אתה יכול להשיג את כל מה שאתה רוצה באמצעות ספק בלבד. אני אראה לך.

הספק

אנו ניצור ספק שמחזיר ערך ופשוט יציג ערך זה, הייתם עושים זאת:

var mod = angular.module ("MyModule", []); mod.provider ("myProvider", פונקציה () {זה. $ get = function () {return "הערך שלי;};}); mod.controller ("MyController", פונקציה (myProvider) {console.log ("MyController - myProvider:" + myProvider);}); CONSOLE OutPUT MyController - myProvider: הערך שלי

דוגמה אינטראקטיבית עובדת ניתן למצוא ב: JS Fiddle.

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

שים לב בדגימות קוד נוספות אני הולך להחריג את ה- תג והגדרת ה- mod לצורך שמירה על קטעי קוד קצרים עד כדי כך.

זוויתית מקבלת רק את הערך פעם-פעם

שים לב שזוויתית "מקבלת" רק את הערך פעם אחת, לא משנה כמה פעמים מוזרק הספק. פירוש הדבר שהוא מתקשר ל- $ get () פעם אחת בלבד, אוגר את הערך שמספק $ get () ומעניק לך את אותו ערך מאוחסן בכל פעם.

כדי להראות לך למה אני מתכוון אצור בקר נוסף ואזריק לספק לספק הצהרת קונסולה כדי שתוכל לראות מה קורה.

mod.provider ("myProvider", פונקציה () {זה. $ get = function () {console.log ("MyProviderFunction. $ get () נקרא."); // הוסיף שורה זו להחזיר "הערך שלי";}; }); mod.controller ("MyController", פונקציה (myProvider) {console.log ("MyController - myProvider:" + myProvider);}); mod.controller ("MyController2", פונקציה (myProvider) {// הוסיף console.log של בקר זה ("MyController2 - myProvider:" + myProvider);}); CONSOLE OUTPUT MyProviderFunction. $ Get () התקשר. MyController - myProvider: הערך שלי MyController2 - myProvider: הערך שלי

פתוח ב- JS Fiddle

כפי שניתן לראות הפונקציה $ get () נקראה פעם אחת בלבד.

שימו לב שכתבנו חבורה של קוד לספק רק לצורך יצירת שיטה שנקראת $ get (). מדוע לא במקום לתת לזווית פונקציה המגדירה פונקציה אחרת, מדוע לא פשוט לתת לה את הפונקציה אותה אנו רוצים להפעיל ישירות במקום זאת? ובכן אתה יכול, זה מה שמכונה אנגולר מפעל.

מפעל

עם מפעל אתה פשוט מספק את גוף הפונקציה בשיטת $ get ו- Angular עושה את השאר. להלן נראה הקוד החדש, כפי שאתה תראה שהוא מתנהג בדיוק אותו הדבר.

mod.factory ("myProvider", פונקציה () {// שינוי "ספק" ל"מפעל "console.log (" פונקצית מפעל נקראת. "); החזר" הערך שלי ";}); mod.controller ("MyController", פונקציה (myProvider) {console.log ("MyController - myProvider:" + myProvider);}); mod.controller ("MyController2", פונקציה (myProvider) {console.log ("MyController2 - myProvider:" + myProvider);}); פלט CONSOLE מפעל שנקרא. MyController - myProvider: הערך שלי MyController2 - myProvider: הערך שלי

פתוח ב- JS Fiddle

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

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

לדוגמא, בואו נעשה זאת על ידי החזרת אובייקט המכיל פונקציה שנקראת getValue (). כעת ישנן מספר דרכים בהן ניתן ליצור אובייקט ב- JavaScript, אנו נשתמש בגישה "Object Constructor" בה אנו יוצרים פונקציה המאכלסת אובייקט עם מאפיינים ופונקציות ומשתמשת במילת המפתח החדשה כדי לייצר אותו.

פונקציה MyObject () {// הוסיף לבנאי האובייקטים שלנו this.getValue = function () {return "הערך שלי"; }; } mod.factory ("myProvider", פונקציה () {console.log ("פונקצית מפעל נקראת."); החזיר את MyObject החדש (); // CREATE מופע של האובייקט שלנו}); mod.controller ("MyController", פונקציה (myProvider) {console.log ("MyController - myProvider:" + myProvider.getValue ()); // שינוי להתקשר getValue ()}); mod.controller ("MyController2", פונקציה (myProvider) {console.log ("MyController2 - myProvider:" + myProvider.getValue ()); // שינוי להתקשר getValue ()}); פלט CONSOLE מפעל שנקרא. MyController - myProvider: הערך שלי MyController2 - myProvider: הערך שלי

פתוח ב- JS Fiddle

עכשיו אני רוצה לעשות ציר אחד קטן לזה כי זה יוביל יפה לקונספט הבא. בדוגמה שלנו אנו יוצרים את פונקציית "Object Constructor" MyObject (), אך מכיוון שאנחנו רק מייצרים אותה במקום אחד, אנו יכולים להשתמש בפונקציה אנונימית במקום.

זהו ציוץ קטן מאוד. במקום זה:

פונקציה MyObject () {this.getValue = פונקציה () {להחזיר את "הערך שלי"; }; } mod.factory ("myProvider", פונקציה () {console.log ("פונקצית מפעל נקראת."); החזיר את MyObject החדש ();});

אנו עושים זאת:

mod.factory ("myProvider", פונקציה () {console.log ("פונקצית מפעל נקראת."); להחזיר פונקציה חדשה () {// INLINED בנאי האובייקטים שלנו this.getValue = function () {return "My Value"; };};});

אז כל העניין נראה עכשיו כך:

mod.factory ("myProvider", פונקציה () {console.log ("פונקצית מפעל נקראת."); להחזיר פונקציה חדשה () {// INLINED בנאי האובייקטים שלנו this.getValue = function () {return "My Value"; };};}); mod.controller ("MyController", פונקציה (myProvider) {console.log ("MyController - myProvider:" + myProvider.getValue ());}); mod.controller ("MyController2", פונקציה (myProvider) {console.log ("MyController2 - myProvider:" + myProvider.getValue ());});

פתוח ב- JS Fiddle

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

לשירותכם

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

mod.service ("myProvider", פונקציה () {// שינוי "מפעל" ל"שירות "// שימו לב שהפונקציה היחידה שמועברת היא בנאי האובייקטים שלפני this.getValue = function () {return" הערך שלי " ;};}); mod.controller ("MyController", פונקציה (myProvider) {console.log ("MyController - myProvider:" + myProvider.getValue ());}); mod.controller ("MyController2", פונקציה (myProvider) {console.log ("MyController2 - myProvider:" + myProvider.getValue ());}); CONSOLE OutPUT MyController - myProvider: My Value MyController2 - myProvider: My Value

פתוח ב- JS Fiddle

ספק מול מפעל לעומת שירות

אז לסיכום, ספק, מפעל ושירות כולם ספקים. מפעל הוא מקרה מיוחד של ספק כאשר כל מה שאתה צריך בספק הוא פונקציה של $ get (). זה מאפשר לך לכתוב את זה עם פחות קוד. שירות הוא מקרה מיוחד של מפעל כשרוצים להחזיר מופע של אובייקט חדש, עם אותו יתרון של כתיבת פחות קוד.

מתי להשתמש באחד לעומת השני?

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

mod.factory ("myProvider", פונקציה () {console.log ("פונקצית מפעל נקראת."); החזיר את SomeMessageBoxClass ("טיעון מותאם אישית");

אחד הגורמים העיקריים להחלטה בין ספק למפעל הוא האם אתה רוצה להיות מסוגל להגדיר את האובייקט שנוצר לפני שהוא נוצר. אתה עושה זאת על ידי חיוג module.config () וקבלת מופע לספק עצמו (במקום האובייקט שיוחזר על ידי הספק). אתה עושה זאת על ידי הוספת "ספק" לסוף שם הספק כשאתה מזריק אותו.

להלן דוגמא כיצד הייתם עושים זאת:

mod.provider ("myProvider", פונקציה () {this.value = "הערך שלי"; this.setValue = פונקציה (newValue) {this.value = newValue;}; זה. $ get = function () {להחזיר את זה. ערך; }; }); mod.controller ("MyController", פונקציה (myProvider) {console.log ("MyController - myProvider:" + myProvider);}); mod.config (פונקציה (myProviderProvider) {// ADDED סעיף config // שימו לב לסיומת "ספק" הנוספת myProviderProvider.setValue ("ערך חדש");});

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

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

mod.factory ("myProvider", פונקציה () {להחזיר את "הערך שלי";});

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

mod.value ("myProvider", "הערך שלי");

אז מתי היית משתמש בזה אחד לעומת השני? יש להניח שתשתמש במפיק המפעל כאשר ברצונך לחשב את הערך על סמך נתונים אחרים, למשל נתונים מספק ספק אחר או ממקור חיצוני. ו / או כשרוצים לחשב את הערך אם ורק כאשר הוא מבקש לראשונה. הנה כמה דוגמאות:

// דוגמא היכן המפעל תלוי בספק "ערך" mod.value ("מרובה", 3); mod.factory ("ערך", פונקציה (מרובה) {להחזיר 10 * מרובה;}); // דוגמה שבה מפעל תלוי בנתונים חיצוניים mod.factory ("ערך", פונקציה (מרובה) {var multiple = getDateFromExternalPage (); החזר 10 * מרובים;});

האם רמזתי שהערך הוא הספק האחר היחיד? ובכן שיקרתי, יש עוד אחד שדומה מאוד לערך עם שני הבדלים קלים. ספק זה נקרא קבוע.

ההבדל בין ערך לקבוע הוא שערך שצוין באמצעות קבוע זמין בשלב התצורה. אולי תזכרו מקודם שציינתי כי ספק זה היה נגיש משלב התצורה, אך השירות והמפעל לא היו.

ובכן זה אותו דבר לגבי ערך קבוע. קבוע זמין משלב התצורה והערך אינו. ההבדל הנוסף הוא כשמו כן הוא כי אינך יכול לשנות את הערך של קבוע. הערך הראשון שאתה מקצה אותו הוא הערך שהוא שומר, אם אתה מנסה להקצות לו ערך אחר בהמשך הוא יתעלם.

להלן דוגמא:

mod.value ("myValue", "הקצאה ראשונה"); mod.value ("myValue", "הקצאה שנייה"); mod.constant ("myConstant", "הקצאה ראשונה"); mod.constant ("myConstant", "הקצאה שנייה"); mod.controller ("MyController", פונקציה (myValue, myConstant) {console.log ("myValue:" + myValue); console.log ("myConstant:" + myConstant);}); תפוקת קונסולה myValue: הקצאה שנייה myConstant: הקצאה ראשונה

להלן סיכום מתי להשתמש בכל אחד מהם:

ערך

אתה מספק ערך מילולי פשוט.

mod.value ("myValue", 10);
    

קבוע

אתה צריך להיות מסוגל לגשת לערך זה בשלב התצורה. (באמצעות .config ())

mod.constant ("myValue", 10); mod.config (פונקציה (myValue) {console.log (myValue);});

מפעל

יש לחשב את הערך שאתה מספק על סמך נתונים אחרים.

mod.factory ("myFactory", פונקציה () {return 10;});
        

שירות

אתה מחזיר אובייקט בשיטות.

mod.service ("myService", פונקציה () {var name = "Bob"; this.setName = פונקציה (newName) {this.name = newName;}; this.getName = פונקציה () {להחזיר this.name;} });
        

ספק

אתה רוצה להיות מסוגל להגדיר, במהלך שלב התצורה, את האובייקט שעומד ליצור לפני שהוא נוצר.

mod.provider ("יותר טוב", פונקציה () {var name; this.setName = פונקציה (newName) {name = newName;}; זה. $ get = function () {להחזיר פונקציה חדשה () {this.sayHi = פונקציה () {console.log ("היי" + שם;};};};}); mod.config (פונקציה (greeterProvider) {greeterProvider.setName ("John");});
        

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


תשובה 2:

באופן פנימי AngularJS משתמש במפעל כדי ליצור אובייקט שירות ומשתמש בספק כדי ליצור אובייקט מפעל.

מפעל עושה,

  1. צור אובייקט / מופע בנה / אתחל את האובייקט שנוצר / הפעל את האובייקט / מופע שנוצר

כדי להגדיר הקשר, ראו את Angular Factory כדפוס עיצוב מפעל מופשט. AngularJS נותן לך אפשרות ליצור אובייקט לפי בחירתך בשיטת המפעל שלך, אתה מחזיר את האובייקט שנוצר עבור היישום שלך לשירות.

להלן דוגמה, יש לך אפשרות לבחור בין שני שערים לתשלום, מישהו המשתמש בקוד / הספריה שלך, שיטת המפעל שלך יכולה לבחור אם ליצור אובייקט Paypal או Stripe. זה דומה מאוד ל- Abstract Factory, המשתמשים ב- PaymentService אינם מודעים לאיזה שירות משמש לשער תשלום.

var myModule = angular.module ('myModule', []); myModule.constant ("PaymentGatewayName", "פס"); // או "Paypal" myModule.factory ('paymentService', פונקציה (PaymentGatewayName) {var paymentService; // אתה מחליט איזה אובייקט ליצור על בסיס צורך עסקי // StripeGateway ו- PaypalGateway הם שיעורי JavaScript // מכיל יישום ספציפי ל- Gateway אם ( PaymentGatewayName == "Stripe)) {PaymentService = StripeGateway חדש (); // קוד מותאם אישית לאתחול שער פס} אחר (PaymentGatewayName ==" Paypal ") {PaymentService = חדש PaypalGateway (); // קוד מותאם אישית לאתחל paypal} / / קוד מותאם אישית לאתחל PaymentService להחזיר PaymentService;});

קוד שירות נראה כך, אתה מבחין במילת מפתח "זו", כלומר אובייקט כבר נוצר עבורך על ידי Angular Core, אינך שולט יותר ביצירת אובייקטים.

var myModule = angular.module ('myModule', []); myModule.service ('מטמון', פונקציה () {var localVariable = ""; לא ניתן לגשת אל מחוץ // this.cacheSize = 5; // 5 MB this.objectsSize = 1000; // max 1000 objects this.put = function (מפתח, ערך) {...} this.get = פונקציה (קבל) {חזרה ...}});

תשובה 3:

השאלה הגדולה ב- AngularJS: Service vs Factory v / s Provider. במה עלי להשתמש?

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

אם אתה חושב שהם דומים - אתה צודק. הם דומים מאוד. למעשה, כולם אותו דבר. כולם ספקים.

קרא את המאמר המלא -> AngularJS: שירות v / s ספק מפעל v / s - התכונן לראיון תוך 15 דקות