كما تعلم ، فإن بيئة تنفيذ لغة JavaScript هي "موضوع واحد".
يعني ما يسمى "موضوع واحد" أنه لا يمكن إكمال مهمة واحدة إلا في وقت واحد. إذا كانت هناك مهام متعددة ، فيجب عليك الانتظار ، وإكمال المهمة السابقة ، وتنفيذ المهمة التالية ، وما إلى ذلك.
ميزة هذا النموذج هي أنه من السهل نسبيًا التنفيذ وأن بيئة التنفيذ بسيطة نسبيًا ؛ العيب هو أنه طالما كانت هناك مهمة تستغرق وقتًا طويلاً ، يجب وضع المهام اللاحقة في قائمة الانتظار ، مما سيؤخر تنفيذ البرنامج بأكمله. المتصفحات الشائعة لا تستجيب (موت مزيف) في كثير من الأحيان لأن جزءًا معينًا من رمز JavaScript يعمل لفترة طويلة (مثل حلقة ميتة) ، مما يتسبب في تعليق الصفحة بأكملها في هذا المكان ولا يمكن تنفيذ المهام الأخرى.
لحل هذه المشكلة ، تقسم لغة JavaScript طريقة التنفيذ للمهام إلى نوعين: متزامن (متزامن) وغير متزامن (غير متزامن).
"الوضع المتزامن" هو نمط القسم السابق. تنتظر المهمة الأخيرة أن تنتهي المهمة السابقة ثم تنفذها. ترتيب تنفيذ البرنامج متسق ومتزامن مع ترتيب الترتيب للمهام ؛ يختلف "الوضع غير المتزامن" تمامًا. كل مهمة لديها وظائف رد اتصال واحدة أو أكثر (عروض التراجعات). بعد انتهاء المهمة السابقة ، ليست المهمة التالية ، ولكن يتم تنفيذ وظيفة رد الاتصال. يتم تنفيذ المهمة الأخيرة دون انتظار انتهاء المهمة السابقة ، وبالتالي فإن ترتيب تنفيذ البرنامج غير متناسق وغير متزامن مع ترتيب الترتيب للمهام.
"وضع Async" مهم للغاية. على جانب المتصفح ، يجب تنفيذ العمليات طويلة الأجل بشكل غير متزامن لتجنب المتصفح من فقدان الاستجابة. أفضل مثال هو عمليات AJAX. على جانب الخادم ، فإن "الوضع غير المتزامن" هو الوضع الوحيد ، لأن بيئة التنفيذ متطورة ، إذا تم السماح بجميع طلبات HTTP بشكل متزامن ، فسوف ينخفض أداء الخادم بشكل حاد وسوف يفقد رده قريبًا.
تلخص هذه المقالة 4 طرق لبرمجة "الوضع غير المتزامن". يتيح لك فهمها كتابة برامج JavaScript بهيكل أكثر منطقية وأداء أفضل وصيانة أكثر ملاءمة.
1. وظيفة رد الاتصال
هذه هي الطريقة الأساسية للبرمجة غير المتزامنة.
افترض أن هناك وظيفتان F1 و F2 ، وهما في انتظار نتيجة التنفيذ للأولى.
نسخة الكود كما يلي:
F1 () ؛
F2 () ؛
إذا كانت F1 مهمة تستغرق وقتًا طويلاً ، فيمكنك التفكير في إعادة كتابة F1 وكتابة F2 كوظيفة رد الاتصال لـ F1.
نسخة الكود كما يلي:
وظيفة F1 (رد الاتصال) {
setTimeout (function () {
// رمز مهمة F1
أتصل مرة أخرى()؛
} ، 1000) ؛
}
يصبح رمز التنفيذ هكذا:
نسخة الكود كما يلي:
F1 (F2) ؛
وبهذه الطريقة ، نقوم بتحويل العمليات المتزامنة إلى عمليات غير متزامنة. لن تمنع F1 عملية البرنامج ، والتي تعادل تنفيذ المنطق الرئيسي للبرنامج أولاً وتأجيل تنفيذ عملية المستهلكة للوقت.
تتمثل ميزة وظائف رد الاتصال في أنها بسيطة وسهلة الفهم ونشرها ، والعيوب هي أنها لا تفضي إلى قراءة الكود وصيانته. إنها مقترنة للغاية (اقتران) بين الأجزاء المختلفة ، وستكون العملية فوضوية للغاية ، ويمكن لكل مهمة فقط تحديد وظيفة رد اتصال واحد.
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. نشر/اشتراك
يمكن فهم "الحدث" في القسم السابق تمامًا على أنه "إشارة".
نحن نفترض أن هناك "مركز إشارة". بعد الانتهاء من المهمة ، يتم نشر إشارة إلى مركز الإشارة. يمكن للمهام الأخرى "الاشتراك" في الإشارة إلى مركز الإشارة ، وذلك لمعرفة متى يمكن أن تبدأ التنفيذ. وهذا ما يسمى "نمط النشر-subscried" ، والمعروف أيضًا باسم "نمط المراقب".
هناك العديد من تطبيقات هذا النموذج. فيما يلي حانة Ben Allman Tiny Pub/Sub ، والتي تعد مكونًا إضافيًا لـ JQuery.
أولاً ، يشترك 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) ؛
علاوة على ذلك ، يتمتع بميزة عدم وجود أي من الطرق الثلاثة السابقة: إذا تم الانتهاء من المهمة ، فأضف وظيفة رد الاتصال ، وسيتم تنفيذ وظيفة رد الاتصال على الفور. لذلك ، لا داعي للقلق بشأن فقدان حدث أو إشارة. عيب هذه الطريقة هو أنه من الصعب نسبيًا الكتابة والفهم.