كيفية تشغيل حلقات غير متزامنة بالترتيب أو بالتوازي في JavaScript؟
قبل القيام بالسحر غير المتزامن ، أود أن أذكركم بحلقات الحلقات الكلاسيكية المتزامنة.
حلقات متزامنة
منذ وقت طويل كتبت الحلقات بهذه الطريقة (ربما أنت أيضًا):
for (var i=0; i < array.length; i++) { var item = array[i];
هذه الدورة جيدة وسريعة. ولكن لديه الكثير من المشاكل مع سهولة القراءة والدعم. بعد فترة ، اعتدت على أفضل إصدار لها:
array.forEach((item) => {
جافا سكريبت تتطور بسرعة كبيرة. تظهر ميزات جديدة وبناء جملة. أحد التحسينات المفضلة لدي هي المزامنة / الانتظار .
الآن يمكنني استخدام بناء الجملة هذا في كثير من الأحيان. وفي بعض الأحيان تكون هناك مواقف عندما أحتاج إلى القيام بشيء مع عناصر الصفيف بشكل غير متزامن.
حلقات غير متزامنة
كيفية استخدام await
في جسم الحلقة؟ دعنا فقط نحاول كتابة وظيفة غير متزامنة ونتوقع مهمة معالجة كل عنصر:
async function processArray(array) { array.forEach(item => {
هذا الكود سوف يلقي خطأ. لماذا؟ لأننا لا نستطيع استخدام await
داخل وظيفة متزامن. كما ترون ، processArray
هي وظيفة غير متزامنة. لكن الوظيفة المجهولة التي نستخدمها في forEach
متزامنة .
ما الذي يمكن عمله حيال ذلك؟
1. لا تنتظر نتيجة التنفيذ
يمكننا تعريف وظيفة مجهولة بأنها غير متزامنة:
async function processArray(array) { array.forEach(async (item) => { await func(item); }) console.log('Done!'); }
ولكن forEach
لن تنتظر المهمة لإكمالها. forEach
هي عملية متزامنة. وقالت إنها ببساطة سوف تبدأ المهام والمضي قدما. دعونا نتحقق من اختبار بسيط:
function delay() { return new Promise(resolve => setTimeout(resolve, 300)); } async function delayedLog(item) {
في وحدة التحكم ، سنرى:
Done! 1 2 3
في بعض الحالات ، قد تكون هذه نتيجة طبيعية. ولكن لا يزال ، في معظم الحالات ، هذا ليس منطقًا مناسبًا.
2. معالجة الدورة بالتتابع
من أجل انتظار نتيجة تنفيذ جسم الحلقة ، نحتاج إلى العودة إلى الحلقة القديمة "الجيدة". ولكن هذه المرة سوف نستخدم نسختها الجديدة مع for..of
(بفضل بروتوكول التكرار ):
async function processArray(array) { for (const item of array) { await delayedLog(item); } console.log('Done!'); }
هذا سوف يعطينا النتيجة المتوقعة:
1 2 3 Done!
سيتم معالجة كل عنصر من الصفيف بالتتابع. لكن يمكننا تشغيل الحلقة بالتوازي!
3. معالجة الحلقة في نفس الوقت
تحتاج إلى تعديل الرمز قليلاً لبدء العمليات بشكل متوازٍ:
async function processArray(array) {
يمكن تشغيل هذا الرمز عدة مهام delayLog
متواز. ولكن كن حذرا مع صفائف كبيرة. يمكن أن تكون المهام كثيرة جدًا صعبة للغاية بالنسبة لوحدة المعالجة المركزية والذاكرة.
أيضا ، يرجى عدم الخلط بين "المهام الموازية" من المثال مع التوازي الحقيقي والخيوط. هذا الرمز لا يضمن التنفيذ الموازي. كل شيء يعتمد على نص الحلقة (في المثال ، يتم delayedLog
). يمكن إجراء طلبات الشبكة وأخصائيي الويب وبعض المهام الأخرى بشكل متوازٍ.