كما تعلم ، فإن بيئة تنفيذ لغة JavaScript هي "موضوع واحد".
يعني ما يسمى "موضوع واحد" أنه لا يمكن إكمال مهمة واحدة إلا في وقت واحد. إذا كانت هناك مهام متعددة ، فيجب عليك الانتظار ، وإكمال المهمة السابقة ، وتنفيذ المهمة التالية ، وما إلى ذلك.
ميزة هذا النموذج هي أنه من السهل نسبيًا التنفيذ وأن بيئة التنفيذ بسيطة نسبيًا ؛ تنفيذ البرنامج بأكمله. المتصفحات الشائعة لا تستجيب (موت مزيف) في كثير من الأحيان لأن جزءًا معينًا من رمز JavaScript يعمل لفترة طويلة (مثل حلقة ميتة) ، مما يتسبب في تعليق الصفحة بأكملها في هذا المكان ولا يمكن تنفيذ المهام الأخرى.
لحل هذه المشكلة ، تقسم لغة JavaScript طريقة التنفيذ للمهام إلى نوعين: متزامن (متزامن) وغير متزامن (غير متزامن).
"الوضع المتزامن" هو وضع القسم السابق ، وينتظر المهمة الأخيرة المهمة السابقة ، ثم ينفذها مختلفة تمامًا ، كل مهمة واحدة أو أكثر من وظائف رد الاتصال (عمليات الاسترجاع). لإنهاء ، فإن ترتيب تنفيذ البرنامج والمهمة.
"وضع Async" مهم للغاية. على جانب المتصفح ، يجب تنفيذ العمليات طويلة الأجل بشكل غير متزامن لتجنب المتصفح من فقدان الاستجابة. على جانب الخادم ، فإن "الوضع غير المتزامن" هو الوضع الوحيد ، لأن بيئة التنفيذ متطورة ، إذا تم السماح بجميع طلبات HTTP بشكل متزامن ، فسوف ينخفض أداء الخادم بشكل حاد وسوف يفقد رده قريبًا.
1. وظيفة رد الاتصال
هذه هي الطريقة الأساسية للبرمجة غير المتزامنة.
لنفترض أن هناك وظيفتان F1 و F2 ، وهما ينتظران نتيجة التنفيذ للأولى.
نسخة الكود كما يلي:
F1 () ؛
F2 () ؛
إذا كانت F1 مهمة تستغرق وقتًا طويلاً ، فيمكنك التفكير في إعادة كتابة F1 وكتابة F2 كوظيفة رد الاتصال لـ F1.
نسخة الكود كما يلي:
وظيفة F1 (رد الاتصال) {
setTimeout (function () {
// رمز مهمة F1
أتصل مرة أخرى()؛
} ، 1000) ؛
}
يصبح رمز التنفيذ هكذا:
F1 (F2) ؛
تتمثل ميزة وظائف رد الاتصال في أنها بسيطة وسهلة الفهم ونشرها ، والعيوب هي أنها لا تفضي إلى قراءة الكود وصيانتها. فوضوي للغاية ، ويمكن لكل مهمة فقط تحديد وظيفة رد اتصال واحد.
2. مراقبة الحدث
فكرة أخرى هي تبني نموذج يحركه الحدث. لا يعتمد تنفيذ المهمة على ترتيب الكود ، ولكن على ما إذا كان حدث ما يحدث.
لنأخذ F1 و F2 كأمثلة. أولاً ، ربط حدث لـ F1 (طريقة كتابة jQuery المستخدمة هنا).
نسخة الكود كما يلي:
f1.On ('Done' ، f2) ؛
يعني السطر المذكور أعلاه أنه عند حدوث الحدث الذي تم في F1 ، سيتم تنفيذ F2. ثم ، أعد كتابة F1:
نسخة الكود كما يلي:
وظيفة F1 () {
setTimeout (function () {
// رمز مهمة F1
f1.trigger ('done') ؛
} ، 1000) ؛
}
f1.trigger ('Done') يعني أنه بعد الانتهاء من التنفيذ ، يتم تشغيل الحدث الذي تم القيام به على الفور ، وبالتالي بدأ تنفيذ F2.
تتمثل ميزة هذه الطريقة في أنه من السهل الفهم نسبيًا ربط أحداث متعددة ، ويمكن لكل حدث تحديد وظائف رد الاتصال المتعددة ، ويمكن أن يكون "فك" ، وهو ما يفضي إلى modularization. العيب هو أن البرنامج بأكمله سيعتمد على الحدث ، وستصبح عملية التشغيل غير واضحة للغاية.
3. نشر/اشتراك
يمكن فهم "الحدث" في القسم السابق تمامًا على أنه "إشارة".
نحن نفترض أن هناك "مركز إشارة". وهذا ما يسمى "Publish-Subscribe Pattern" ، والمعروف أيضًا باسم "نمط المراقب".
هناك العديد من تطبيقات هذا النموذج.
أولاً ، يشترك F2 في إشارة "Done" في jQuery "Center Center".
نسخة الكود كما يلي:
jQuery.Subscribe ("Done" ، f2) ؛
ثم ، يتم إعادة كتابة F1 على النحو التالي:
نسخة الكود كما يلي:
وظيفة F1 () {
setTimeout (function () {
// رمز مهمة F1
jQuery.Publish ("Done") ؛
} ، 1000) ؛
}
تعني jQuery.Publish ("Done") أنه بعد الانتهاء من التنفيذ F1 ، يتم إصدار إشارة "تم" إلى "مركز الإشارة" ، مما يؤدي إلى تنفيذ F2.
بالإضافة إلى ذلك ، بعد تنفيذ F2 ، يمكن أيضًا إلغاء إلغاء الاشتراك.
نسخة الكود كما يلي:
jQuery.Unsubscribe ("done" ، f2) ؛
تشبه طبيعة هذا النهج "الاستماع إلى الأحداث" ، ولكنه أفضل بكثير من الأخير. نظرًا لأنه يمكننا مراقبة تشغيل البرنامج من خلال النظر إلى "مركز الرسائل" لفهم عدد الإشارات الموجودة وعدد المشتركين لكل إشارة.
4. وعود الكائن
كائن الوعود هو المواصفات التي اقترحتها مجموعة عمل CommonJS ، مع الغرض من توفير واجهة موحدة للبرمجة غير المتزامنة.
ببساطة ، فكرتها هي أن كل مهمة غير متزامنة تُرجع كائن الوعد ، الذي يحتوي على طريقة تسمح بتحديد وظيفة رد الاتصال. على سبيل المثال ، يمكن كتابة وظيفة رد الاتصال F2 من F1 على النحو التالي:
نسخة الكود كما يلي:
f1 (). ثم (f2) ؛
يجب إعادة كتابة F1 على النحو التالي (يتم استخدام تنفيذ jQuery هنا):
نسخة الكود كما يلي:
وظيفة F1 () {
var dfd = $ .deferred () ؛
setTimeout (function () {
// رمز مهمة F1
dfd.Resolve () ؛
} ، 500) ؛
إرجاع dfd.promise ؛
}
ميزة الكتابة بهذه الطريقة هي أن وظيفة رد الاتصال أصبحت طريقة كتابة السلسلة ، ويمكن رؤية تدفق البرنامج بوضوح شديد ، وهناك مجموعة كاملة من الأساليب الداعمة التي يمكن أن تحقق العديد من الوظائف القوية.
على سبيل المثال ، حدد وظائف رد الاتصال المتعددة:
F1 (). ثم (F2). ثم (F3) ؛
على سبيل المثال ، حدد وظيفة رد الاتصال عند حدوث خطأ:
f1 (). ثم (f2) .fail (f3) ؛
علاوة على ذلك ، يتمتع بميزة عدم وجود أي من الطرق الثلاثة السابقة: إذا تم الانتهاء من المهمة ، فأضف وظيفة رد الاتصال ، وسيتم تنفيذ وظيفة رد الاتصال على الفور. لذلك ، لا داعي للقلق بشأن فقدان حدث أو إشارة. عيب هذه الطريقة هو أنه من الصعب نسبيًا الكتابة والفهم.