جافاسكريبت - كيف يقوم Nodejs بالقيام بعمليات الإدخال/الإخراج تحت الغطاء؟


أعلم أن Node.js يستخدم مجموعة الخيوط التي يوفرها libuv للقيام بالمهام المتزامنة. قرأت أن Node.js يحتاج فقط إلى أحد هذه الخيوط للقيام بجميع الأنشطة المتعلقة بالإدخال/الإخراج.

إذن كيف تحدث عمليات الملفات غير المحجوزة؟

ما الذي سيحدث فعليًا خلف الكواليس بين العقدة والقرص ونظام التشغيل إذا قمت بالتكرار على مجلد يحتوي على 100 ملف وفتحت جميعها باستخدام readFile()؟

إذا كان تنفيذ هذه العملية نفسها في بعض اللغات متعددة الخيوط والمانعة سيؤدي إلى انتظار الخيوط لانتهاء الإدخال/الإخراج، فمن ينتظر انتهاء الإدخال/الإخراج في Node.js؟ خاصة عندما تكون هناك عمليات ملفات متعددة تحدث في الوقت نفسه؟

شكراً لك!

الإجابة رقم 1

يستخدم الإدخال والإخراج للملفات في Node.js مجموعة من الخيوط. بشكل افتراضي، هناك 4 خيوط في المجموعة.

عندما يستدعي بعض كود الجافاسكريبت عملية ملف مثل fs.open() في nodejs، يتم توجيه الاستدعاء إلى بعض الكود الأصلي داخل مكتبة libuv في تنفيذ nodejs. يقوم هذا الكود بإضافة عملية الملف المحددة إلى قائمة انتظار للعناصر التي تنتظر خيط نظام التشغيل. إذا كان خيط نظام التشغيل متاحًا على الفور، يتم إعطاء ذلك الخيط مهمة تنفيذ عملية الملف ثم تعود دالة libuv الأصلية، التي تعود بعد ذلك إلى الجافاسكريبت الأصلية ويستمر nodejs في تشغيل جافاسكريبت الأخرى.

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

عندما ينتهي Node.js من تنفيذ أي كود Javascript آخر كان يشغله، يقوم بسحب الحدث التالي من قائمة الأحداث ويستدعي رد النداء في Javascript المرتبط بذلك الحدث ويمرر له البيانات المرتبطة بالحدث. هذا يؤدي إلى استدعاء رد النداء في Javascript الذي تم تمريره في الأصل إلى fs.open().

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

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