بالنسبة للمبتدئين ، هل يمكن لأي شخص توضيح الفرق بين الخدمة والمصنع والمزود في AngularJS؟


الاجابه 1:

AngularJS: الفرق بين Service و Provider vs Factory

إذا كنت تبحث عن هذا ، فمن المحتمل أنك تحاول معرفة ما هو الأنسب لك. أو لأنك واجهت الثلاثة منهم وتحاول تحديد الفرق لأنها تبدو متشابهة.

إذا كنت تعتقد أنها متشابهة - أنت على حق. كانت متشابهة جدا. في الواقع ، إنهم جميعا نفس الشيء.

انهم جميعا مقدمي. المصنع والخدمة عبارة عن حالات خاصة لمزود الخدمة ، ولكن يمكنك إنجاز كل ما تريد باستخدام المزود فقط. سأريكم.

المزود

سنقوم بإنشاء موفر يقوم بإرجاع قيمة وببساطة عرض هذه القيمة ، يمكنك القيام بذلك:

var mod = angular.module ("MyModule"، [])؛ mod.provider ("myProvider"، function () {this. $ get = function () {return "My Value"؛}؛})؛ mod.controller ("MyController" ، وظيفة (myProvider) {console.log ("MyController - myProvider:" + myProvider)؛})؛ CONSOLE OUTPUT MyController - myProvider: My Value

يمكن العثور على مثال تفاعلي فعال في: JS Fiddle.

هناك ، لذلك "المزود" في القلب يتيح لك "توفير" قيمة. يمكن أن تكون هذه القيمة أي شيء. في هذه الحالة ، تكون سلسلة ذات قيمة "My Value" ولكن يمكن أن تكون بسهولة عبارة عن وظيفة أو كائن.

لاحظ في نماذج التعليمات البرمجية الإضافية سأستبعد العلامة وتعريف وزارة الدفاع لغرض الحفاظ على رمز مقتطفات قصيرة وإلى هذه النقطة.

الزاوي يحصل فقط على القيمة مرة واحدة - على الإطلاق

لاحظ أن الزاوي فقط "يحصل" على القيمة مرة واحدة ، بغض النظر عن عدد المرات التي يتم فيها حقن الموفر. هذا يعني أنه يستدعي $ get () مرة واحدة فقط على الإطلاق ، ويخزن القيمة التي يوفرها $ get () ، ويمنحك نفس القيمة المخزنة في كل مرة.

لتوضيح ما أعنيه ، سأقوم بإنشاء وحدة تحكم أخرى وحقن الموفر مرة أخرى ببيان وحدة تحكم حتى تتمكن من رؤية ما يحدث.

mod.provider ("myProvider"، function () {this. $ get = function () {console.log ("MyProviderFunction. $ get () call.")؛ // ADDED this line return "My Value"؛}؛ })؛ mod.controller ("MyController" ، وظيفة (myProvider) {console.log ("MyController - myProvider:" + myProvider)؛})؛ mod.controller ("MyController2" ، وظيفة (myProvider) {// ADDED وحدة التحكم هذه console.log ("MyController2 - myProvider:" + myProvider)؛})؛ CONSOLE OUTPUT MyProviderFunction. $ get () call. MyController - myProvider: My Value MyController2 - myProvider: My Value

فتح في JS الكمان

كما ترى ، تم استدعاء الدالة $ get () مرة واحدة فقط.

لاحظ أننا كتبنا مجموعة من التعليمات البرمجية للموفر فقط بغرض إنشاء طريقة تسمى $ get (). لماذا لا بدلا من إعطاء الزاوي وظيفة تحدد وظيفة أخرى ، فلماذا لا نعطيها الوظيفة التي نريد تشغيلها مباشرة بدلا من ذلك؟ حسنًا ، يمكنك أن تسمي Angular المصنع.

مصنع

مع أحد المصانع ، تقوم فقط بتوفير الجسم الوظيفي لطريقة get $ بينما تقوم Angular بالقيام بالباقي. فيما يلي الشكل الذي يبدو عليه الرمز الجديد ، حيث سترى أنه يتصرف تمامًا.

mod.factory ("myProvider"، function () {// CHANGED "provider" to "factory" console.log ("دالة المصنع تسمى.") ؛ إرجاع "My Value"؛})؛ mod.controller ("MyController" ، وظيفة (myProvider) {console.log ("MyController - myProvider:" + myProvider)؛})؛ mod.controller ("MyController2" ، وظيفة (myProvider) {console.log ("MyController2 - myProvider:" + myProvider)؛})؛ CONSOLE OUTPUT وظيفة المصنع تسمى. MyController - myProvider: My Value MyController2 - myProvider: My Value

فتح في JS الكمان

الآن قد تتساءل عن سبب استخدامك لمزود في أي وقت إذا كان بإمكانك تحقيق نفس الشيء مع مصنع برمز أقل. هناك عدة أسباب ، وسأبحث عن ذلك لاحقًا ، والآن أريد أن أبقى ملتزمًا بعنوان هذا المنشور ومعالجة الفرق بين هذين (المزود والمصنع) والخدمة.

لقد قمنا حتى الآن بإرجاع قيمة سلسلة بسيطة ، ولكن من الناحية العملية ، ربما ما نريد أن نرجع معظم الوقت هو كائن. حسنًا ، لن يغير هذا مثالنا كثيرًا ، يمكننا بسهولة تبديل السلسلة التي نعود بها باستخدام كائن بدلاً من ذلك.

على سبيل المثال ، دعونا نفعل ذلك عن طريق إرجاع كائن يحتوي على دالة تسمى getValue (). الآن هناك عدة طرق يمكنك من خلالها إنشاء كائن في JavaScript ، سنستخدم منهج "Object Constructor" حيث نقوم بإنشاء دالة تملأ كائنًا بخصائص ووظائف وتستخدم الكلمة الأساسية الجديدة لإنشاء مثيل لها.

function MyObject () {// ADDED منشئ كائن لدينا this.getValue = function () {return "My Value"؛ }؛ } mod.factory ("myProvider"، function () {console.log ("دالة المصنع تسمى.") ؛ إرجاع MyObject () جديد ؛ // CREATE مثيل لكائننا})؛ mod.controller ("MyController" ، وظيفة (myProvider) {console.log ("MyController - myProvider:" + myProvider.getValue ())؛ // CHANGED للاتصال بـ getValue ()})؛ mod.controller ("MyController2" ، وظيفة (myProvider) {console.log ("MyController2 - myProvider:" + myProvider.getValue ())؛ // CHANGED للاتصال بـ getValue ()})؛ CONSOLE OUTPUT وظيفة المصنع تسمى. MyController - myProvider: My Value MyController2 - myProvider: My Value

فتح في JS الكمان

الآن أريد أن أقوم بتعديل واحد صغير على هذا لأنه سوف يؤدي بشكل جيد إلى المفهوم التالي. في مثالنا ، ننشئ وظيفة "Object Constructor" MyObject () ، ولكن بما أننا نلخصها في مكان واحد فقط ، يمكننا استخدام وظيفة مجهولة بدلاً من ذلك.

هذا هو قرص صغير جدا. بدلا من هذا:

function MyObject () {this.getValue = function () {return "My Value"؛ }؛ } mod.factory ("myProvider"، function () {console.log ("دالة المصنع تسمى.") ؛ إرجاع MyObject ()؛}) جديد؛

نحن نفعل هذا:

mod.factory ("myProvider"، function () {console.log ("دالة المصنع تسمى.") ؛ ارجع دالة جديدة () {// INLINED مُنشئ الكائن الخاص بنا this.getValue = function () {return "My Value"؛ }؛}؛})؛

الأمر كله الآن يبدو كالتالي:

mod.factory ("myProvider"، function () {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 الكمان

الآن نظرًا لأن مصنعنا بالكامل يتكون من كائن واحد ، فلن يكون من الرائع أن نتمكن من إعطاء Angular وظيفة منشئ الكائن بدلاً من الاضطرار إلى كتابة هذا المصنع ذو المظهر غير المرغوب فيه. حسنًا ، أنت محظوظ ، هذا هو بالضبط ما هي الخدمة.

في خدمتكم

في ما يلي نفس الرمز باستثناء استخدام خدمة بدلاً من المصنع.

mod.service ("myProvider"، function () {// CHANGED "factory" to "service" // لاحظ أن الوظيفة الوحيدة التي يتم تمريرها هي مُنشئ الكائن من قبل 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 ())؛})؛ CONSOLE OUTPUT MyController - myProvider: My Value MyController2 - myProvider: My Value

فتح في JS الكمان

موفر مقابل مصنع مقابل الخدمة

حتى في الخلاصة ، الموفر ، المصنع ، والخدمة كلها مزودي. المصنع هو حالة خاصة لمزود عندما يكون كل ما تحتاجه في مزودك هو $ get () وظيفة. انها تسمح لك لكتابتها مع رمز أقل. الخدمة هي حالة خاصة بالمصنع عندما تريد إرجاع مثيل لكائن جديد ، مع نفس فائدة كتابة كود أقل.

متى استخدام واحد مقابل الآخر؟

الجواب هو أنك تستخدم الإصدار الأكثر تخصصًا الذي يحقق هدفك. قل على سبيل المثال أنك تقوم بإرجاع كائن موجود معرف في مكان آخر يأخذ وسيطات المنشئ. لا يمكنك تمرير الحجج إلى الخدمة ، لذلك يمكنك إجراء مكالمة مع مصنع بدلاً من ذلك.

mod.factory ("myProvider"، function () {console.log ("دالة المصنع تسمى.") ؛ قم بإرجاع SomeMessageBoxClass جديد ("الوسيطة المخصصة")؛})؛

أحد العوامل الرئيسية للبت بين الموفر والمصنع هو ما إذا كنت تريد أن تكون قادرًا على تكوين الكائن الذي تم إنشاؤه قبل إنشائه. يمكنك القيام بذلك عن طريق استدعاء module.config () والحصول على مثيل إلى الموفر نفسه (بدلاً من الكائن الذي تم إرجاعه بواسطة الموفر). يمكنك القيام بذلك عن طريق إلحاق "مقدم الخدمة" بنهاية اسم المزود الخاص بك عندما تقوم بحقنه.

فيما يلي مثال لكيفية القيام بذلك:

mod.provider ("myProvider"، function () {this.value = "My Value"؛ this.setValue = function (newValue) {this.value = newValue؛}؛ this. $ get = function () {return this. القيمة؛ }؛ })؛ mod.controller ("MyController" ، وظيفة (myProvider) {console.log ("MyController - myProvider:" + myProvider)؛})؛ mod.config (function (myProviderProvider) {// ADDED config section // لاحظ "الموفر" الإضافي لاحقة myProviderProvider.setValue ("قيمة جديدة")؛})؛

يغطي ذلك وقت استخدام الموفرين الثلاثة: المزود ، المصنع ، والخدمة. يوجد موفر إضافي واحد لم يتم ذكره هنا وهو حالة خاصة أخرى وهي موفر القيمة.

إذا كنت تتذكر عند تقديم موفر المصنع أعلاه لأول مرة ، فقد قدمنا ​​مثالًا بسيطًا على إرجاع قيمة سلسلة. هذا يشبه هذا:

mod.factory ("myProvider"، function () {return "My Value"؛})؛

حسنًا ، كان بإمكاننا فعل ذلك باستخدام موفر القيمة بدلاً من ذلك ، ومرة ​​أخرى ، تتمثل الفائدة في أنه يمكنك فعل ذلك برمز أقل. الكود أدناه يفعل نفس الشيء مثل الكود أعلاه:

mod.value ("myProvider" ، "My Value") ؛

لذا متى ستستخدم واحدًا مقابل الآخر؟ من المفترض أنك ستستخدم مصنع المصنع عندما تريد حساب القيمة بناءً على بعض البيانات الأخرى ، على سبيل المثال بيانات من موفر قيمة آخر أو مصدر خارجي. و / أو عندما تريد حساب القيمة إذا وفقط عند طلبها لأول مرة. وهنا بعض الأمثلة:

// مثال حيث يعتمد المصنع على موفر "value" mod.value ("مضاعف" ، 3) ؛ mod.factory ("value"، function (multip) {return 10 * multiple؛})؛ // مثال حيث يعتمد المصنع على 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)؛})؛ CONSOLE OUTPUT myValue: Second Assignment myConstant: First Assignment

فيما يلي ملخص بموعد استخدام كل:

القيمة

أنت تقدم قيمة حرفية بسيطة.

mod.value ("myValue" ، 10) ؛
    

ثابت

يجب أن تكون قادرًا على الوصول إلى هذه القيمة أثناء مرحلة التكوين. (باستخدام .config ())

mod.constant ("myValue" ، 10) ؛ mod.config (function (myValue) {console.log (myValue)؛})؛

مصنع

يجب أن تحسب القيمة التي تقدمها على أساس بيانات أخرى.

mod.factory ("myFactory"، function () {return 10؛})؛
        

الخدمات

تقوم بإرجاع كائن مع الأساليب.

mod.service ("myService"، function () {var name = "Bob"؛ this.setName = function (newName) {this.name = newName؛}؛ this.getName = function () {return this.name؛} })؛
        

مزود

تريد أن تكون قادرًا على التهيئة ، أثناء مرحلة التهيئة ، الكائن الذي سيتم إنشاؤه قبل إنشائه.

mod.provider ("greeter"، function () {var name؛ this.setName = function (newName) {name = newName؛}؛ this. $ get = function () {return new function () {this.sayHi = function () {console.log ("Hi" + name؛}؛}؛}؛}؛)؛ mod.config (function (greeterProvider) {greeterProvider.setName ("John")؛})؛
        

لتوصيل النقطة إلى المنزل في المرة الأخيرة ، توجد صورة لمزود مع تحديد أجزاء المصنع والقيمة والخدمة:


الاجابه 2:

Internally AngularJS يستخدم Factory لإنشاء كائن خدمة ويستخدم Provider لإنشاء كائن مصنع.

مصنع يفعل ،

  1. إنشاء كائن / مثيلإنشاء / تهيئة الكائن الذي تم إنشاؤه / instancereturn إنشاء كائن / مثيل

لتعيين السياق ، ضع في اعتبارك Angular Factory نمطًا لتصميم Abstract Abstract. يمنحك AngularJS خيار إنشاء كائن من اختيارك باستخدام طريقة المصنع الخاص بك ، يمكنك إرجاع الكائن الذي تم إنشاؤه لتطبيقك كخدمة.

أدناه المثال ، لديك خيار بين بوابتي دفع ، شخص يستخدم الكود / المكتبة الخاصة بك ، يمكن لطريقة المصنع أن تختار ما إذا كنت تريد إنشاء كائن Paypal أو Stripe. هذا يشبه إلى حد كبير "مصنع المستخلص" ، حيث أن مستخدمي خدمة الدفع ليسوا على دراية بالخدمة المستخدمة لبوابة الدفع.

var myModule = angular.module ('myModule'، [])؛ myModule.constant ("PaymentGatewayName" ، "Stripe") ؛ // أو "Paypal" myModule.factory ('paymentService' ، والوظيفة (PaymentGatewayName) {var paymentService ؛ // يمكنك تحديد الكائن الذي سيتم إنشاؤه استنادًا إلى احتياجات العمل // StripeGateway و PaypalGateway هي فئات JavaScript / / تحتوي على تطبيق خاص بـ Gateway إذا كان ( PaymentGatewayName == "Stripe") {paymentService = جديد StripeGateway ()؛ // رمز مخصص لتهيئة gatee gateway} آخر (PaymentGatewayName == "Paypal") {paymentService = جديد PaypalGateway ()؛ // رمز مخصص لتهيئة paypal} / / / رمز مخصص لتهيئة paymentService return paymentService؛})؛

يبدو رمز الخدمة هكذا ، لاحظت الكلمة الأساسية "هذه" ، وهذا يعني أن الكائن تم إنشاؤه بالفعل من قِبل Angular Core ، ولم يعد بإمكانك إنشاء عنصر تحكم.

var myModule = angular.module ('myModule'، [])؛ myModule.service ('Cache'، function () {var localVariable = ""؛ // لا يمكن الوصول إليها خارج this.cacheSize = 5 ؛ // 5 ميغابايت this.objectsSize = 1000 ؛ // 1000 1000 كائن this.put = function (مفتاح ، قيمة) {...} this.get = function (get) {return ...}}) ؛

الاجابه 3:

السؤال الكبير في AngularJS: Service vs Factory v / s Provider. ما الذي يجب علي استخدامه؟

هناك الكثير من الموارد على الإنترنت تناقش الموضوع. اتضح أن هذا السؤال ما زال يظهر كل أسبوع أو نحو ذلك على قنوات مختلفة ، وحتى بعد قراءة الإجابات العشرة الأولى على StackOverflow ، فإنه لا يزال غير واضح.

إذا كنت تعتقد أنها متشابهة - أنت على حق. كانت متشابهة جدا. في الواقع ، إنهم جميعا نفس الشيء. انهم جميعا مقدمي.

قراءة المقال كاملاً -> AngularJS: مزود الخدمة / المصانع s / s - احصل على مقابلة جاهزة في 15 دقيقة