اذهب إلى المحتوى

السؤال

نشر (معدل)

استخدم node js من طرف السيرفر ولدي حلقة تقوم بإنشاء اتصال socket IO مع سيرفر آخر ويجب انتظار النتيجة ثم تنفيذ باقي التعليمات وتكرار الحلقة. ولكن ذلك لا يحصل.

هذا هو الكود:

exports.placeOrders = async (socket, orders) => {
	for await (order of orders){ 
        console.log("Order ID: " + order.id);   

		socket.emit('requestOrderDetails', order.id);

         await socket.on('getDetails' , async (response) => {
                 console.log("order details:" + response);

				await .. 
				await ..


             })

		}
	console.log("Process Finished);
}
    

الحلقة تقوم بالمرور على الطلبات orders وعند كل طلب تقوم بجلب باقي التفاصيل من السيرفر الآخر عن طريق socket.

ولكن بدلاً من الحصول على النتائج بالترتيب أحصل على التالي:

Order ID:

Process Finished

Order details:

ولكن الترتيب الصحيح هو
1-order ID
2-order details
3-process finished

حاولت استخدام for await وأيضاً حلقة for العادية ولكن نفس النتيجة. ما الحل؟

تم التعديل في بواسطة Tamim Fahed

Recommended Posts

  • 0
نشر

عليك تقسم الكود إلى تابعين الأول يمر على orders والثاني ينفذ التعليمات الخاصة بكل order.

التابع الذي يقوم بتنفيذ التعليمات ضمن حلقة for يجب استدعائه عن طريق await.

عند الحاجة لانتظار أكثر من حدث للانتهاء عليك استخدام promise all.

  • 0
نشر

تعمل الدالات غير المتزامنة async  على إرجاع  قيمة Promise ، وهو مكون من شأنه  أن رجعة قيمة معينة أو أن يرجع قيمة خطا (error) .   يعني أن await تطلب من البرنامج التوقف وإنتظار قيمة promise.

في بعض الأحيان نضطر أن نستعمل await داخل حلقة loop مثلا:

const fruits = ['apple', 'grape', 'pear']

  console.log('بداية')

  for (let index = 0; index < fruits.length; index++) {
    const fruit = fruits[index]
    
    // لنفترض أن هذه دالة تقوم بجلب إسم فاكهة معينة من الخادم
    const fruitInfo = await getfruitInfo(fruit)
    
    console.log('fruitInfo')
  }

  console.log('نهاية')
}

//--------------- نتيجة هذا الكود سوف تكون كالتالي ---------------
/*
'بداية'
'Apple'
'Grape'
'Pear'
'نهاية'

*/

في هذه الحالة await تعمل بالشكل المطلوب كما تريد أن تكون في الكود الخاص بك

لكن في حالة كانت getfruitInfo تحتاج إلى callback كمعطى parameter فلن تعمل الحلقة كما يبغي لأن في الحلقة loop يوجد مجموعة من promises لم تنتهي بعد ولذلك تظهر process finished قبل نهاية الحلقة والحل هو إستخدام await Promise.all(arrayOfPromises).

وبالتالي الكود الخاص بك يجب أن يكون على الشكل التالي:

exports.placeOrders = async (socket, orders) => {
	for await (order of orders){ 
        console.log("Order ID: " + order.id);   

		socket.emit('requestOrderDetails', order.id);

       const promises =  await socket.on('getDetails' , async (response) => {
                 console.log("order details:" + response);
             })

		}
      
  // pormises هنا يجب أن نجبر البرنامج على التوقف حتى نهاية جميع  
      const details = await Promise.all(promises)
      
	console.log("Process Finished);
}

 

 

 

  • 0
نشر
بتاريخ 49 دقائق مضت قال محمد أيت لعرايك:

// pormises هنا يجب أن نجبر البرنامج على التوقف حتى نهاية جميع const details = await Promise.all(promises)

مع تعديل الكود إلى هذا الشكل لم يتم التعرف على المتغيّر promises خارج الحلقة وظهر الخطأ التالي:

promises is not defined

  • 0
نشر
بتاريخ 1 دقيقة مضت قال Tamim Fahed:

مع تعديل الكود إلى هذا الشكل لم يتم التعرف على المتغيّر promises خارج الحلقة وظهر الخطأ التالي:

promises is not defined

نعم ما قصده المدرب محمد هو عمل مصفوفة بطول orders من الكائنات promesies وتمريرها للتابع Promise.all

أي أولا يجب تهيئة المصفوفات ثم استدعائهم ومن ثم انتظار النتائج

  • 0
نشر
بتاريخ 9 دقائق مضت قال Tamim Fahed:

مع تعديل الكود إلى هذا الشكل لم يتم التعرف على المتغيّر promises خارج الحلقة وظهر الخطأ التالي:

promises is not defined

انظر الكود جيدا promises معرفة في سطر  

const promises = await socket.on('getDetails' , async (response) => { console.log("order details:" + response); }) }

  • 0
نشر

قم باستبدال for ...of جملة واحدة ب promise.all واستخدم map لتعمل حلقة حول orders وترجع قائمة ل promise.all وهي ستتكفل بالباقي 

exports.placeOrders = async (socket, orders) => {
  Promise.all(
    orders.map(async (order) => {
      console.log('Order ID: ' + order.id);

      socket.emit('requestOrderDetails', order.id);

      await socket.on('getDetails', async (response) => {
        console.log('order details:' + response);

        // await ..
        // await ..
      });
    })
  );
  console.log('Process Finished');
};

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...