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

Node.js -تُلفظ نود جي إس- هو بيئة تشغيل جافاسكربت مفتوحة المصدر تتيح تنفيذ شيفرات جافاسكربت خارج المتصفح، وذلك باستخدام محرك جافاسكربت V8 الشهير المُستخدم ضمن متصفح جوجل كروم، ومن أشهر استخدامات هذه البيئة هو تطوير تطبيقات وخوادم الويب وحتى أدوات سطر الأوامر، وتوفر لنا هذه البيئة كتابة شيفرات الواجهات الأمامية Front-end والواجهات الخلفية Back-end بلغة برمجة واحدة وهي جافاسكربت، كما تتيح لنا ذلك توحيد لغة البرمجة ضمن طبقات المشروع كافة ما يزيد التركيز ويوفر إمكانية لاستخدام نفس المكتبات ومشاركة الشيفرة بين الواجهات الأمامية بطرف العميل والواجهة الخلفية على الخادم.

تتميز بيئة نود بطريقة التنفيذ الغير متزامنة asynchronous execution ما يمنحها قوة وأفضلية بالأداء في تنفيذ المهام التي تتطلب غزارة في الدخل والخرج ضمن في تطبيقات الويب أو تطبيقات الزمن الحقيقي، كتطبيقات بث الفيديو أو التطبيقات التي تحتاج لإرسال واستقبال مستمر للبيانات.

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

المستلزمات

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

الخطوة الأولى - الطباعة إلى الطرفية

المهمة الأولى للمبرمج عند تعلمه للغة برمجة أو تجربة بيئة جديدة هي كتابة برنامج لطباعة عبارة "أهلًا بالعالم!" أو "‎Hello, World!‎"، لذا نبدأ بإنشاء ملف جديد نسميه"hello.js" ونفتحه ضمن أي برنامج محرر نصوص تريد كبرنامج المُفكرة Notepad مثلًا، سنستخدم في هذا المقال المحرر nano من سطر الأوامر كالتالي:

nano hello.js

نكتب الشيفرة التالية داخله ونحفظ الملف:

console.log("Hello World");

يوفر الكائن console في بيئة نود في السطر السابق توابعًا تمكننا من الكتابة إلى مجاري الخرج مثل مجرى الخرج القياسي stdout أو إلى مجرى الخطأ القياسي stderr وغيرهما والتي عادةً تمثل سطر الأوامر، ويطبع التابع log القيم المُمررة له إلى المجرى stdout لتظهر لنا في الطرفية، حيث أن المجاري في نود هي إما كائنات تستقبل بيانات مثل المجرى stdout، أو تُخرج بيانات كمقبس شبكة أو ملف، وأي بيانات تُرسل إلى المجرى stdout أو stderr ستظهر مباشرًة في الطرفية، ومن أهم مزايا المجاري سهولة إمكانية إعادة توجيهها، كتوجيه خرج تنفيذ برنامج ما إلى ملف أو إلى برنامج آخر، والآن وبعد التأكد من حفظ الملف والخروج من محرر النصوص، حيث إذا كنت تستخدم nano اضغط على CTRL+X للخروج واضغط Y عند سؤالك عن حفظ الملف، وبهذا يكون البرنامج الذي كتبناه جاهزًا للتنفيذ.

الخطوة الثانية - تشغيل البرنامج

نستخدم الأمر node لتشغيل البرنامج السابق كالتالي:

node hello.js

سيتم تنفيذ شيفرات البرنامج داخل ملف hello.js ويظهر الناتج ضمن الطرفية:

Hello World

ما حدث هو أن مفسر نود قرأ الملف ونفذ التعليمة ‎console.log("Hello World");‎ عبر استدعاء التابع log من الكائن العام console، الذي مررنا له السلسلة النصية "Hello World" كوسيط، ونلاحظ عدم طباعة علامات الاقتباس التي مررناها على الشاشة، لأنها ضرورية ضمن الشيفرة فقط لتحديد النص كسلسلة نصية، والآن بعد أن نفذنا برنامجنا البسيط السابق بنجاح، سنطوره ليصبح أكثر تفاعلية.

الخطوة الثالثة - استقبال الدخل من المستخدم عبر وسائط سطر الأوامر

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

سنقوم بالتعديل على برنامجنا ليستقبل الدخل من المستخدم عن طريق وسائط سطر الأوامر، لهذا نُنشئ ملفًا جديدًا بالاسم arguments.js:

nano arguments.js

ونكتب داخله الشيفرة التالية ونحفظ الملف:

console.log(process.argv);

يحوي الكائن العام process في نود على توابع وبيانات تتعلق بالإجرائية الحالية، والخاصية argv ضمنه هي مصفوفة سلاسل نصية تُمثل عناصرها وسائط سطر الأوامر المٌمررة للبرنامج عند تنفيذه، وأصبح بإمكاننا الآن تمرير عدة وسائط إلى البرنامج أثناء تنفيذه كالتالي:

node arguments.js hello world

لنحصل على الخرج:

[
   '/usr/bin/node',
  '/home/hassan/first-program/arguments.js',
  'hello',
  'world'
]

يمثل أول وسيط ضمن المصفوفة process.argv مسار الملف التنفيذي لنود الذي نفَّذ البرنامج، بينما الوسيط الثاني هو مسار ذلك البرنامج، والوسائط البقية تمثل الوسائط التي أدخلها المستخدم في حالتنا هي كلمة hello وكلمة world، وهي عادةً ما يهمنا عند التعامل مع الوسائط المُمررة للبرنامج وليس الوسائط التي يمررها نود افتراضيًا.

الآن نفتح ملف البرنامج arguments.js مجددًا لنعدل عليه:

nano arguments.js

ونحذف التعليمة السابقة ونضع بدلًا منها التعليمة التالية:

console.log(process.argv.slice(2));

بما أن الخاصية argv هي مصفوفة Array، يمكننا الاستفادة من التوابع المتاحة ضمن المصفوفات في جافاسكربت، مثل التابع slice لنختار العناصر التي نريدها فقط من المصفوفة، فنمرر له العدد 2 كوسيط لنحصل على كافة عناصر المصفوفة argv بعد العنصر الثاني والتي تمثل الوسائط التي مررها المستخدم بالضبط.

نعيد تنفيذ البرنامج كما نفذناه آخر مرة ونلاحظ الفرق:

node arguments.js hello world

سيظهر لنا الخرج التالي:

[ 'hello', 'world' ]

بعد أن أصبح البرنامج يستقبل الدخل من المستخدم، سنطوره الآن ليعرض لنا متغيرات البيئة المتاحة للبرنامج.

الخطوة الرابعة - الوصول لمتغيرات البيئة

سنعرض في هذه الخطوة متغيرات البيئة environment variables المتاحة في النظام وقيمها باستخدام الكائن العام process.env ونطبعها في الطرفية، فمتغيرات البيئة هي بيانات على شكل مفتاح وقيمة key/value مُخزَّنة خارج البرنامج يوفرها نظام التشغيل، حيث يتم تعيين قيمها إما من قبل النظام أو المستخدم، وتكون متاحة لجميع الإجرائيات لاستخدامها كطريقة لضبط إعدادات البرامج أو حالتها أو طريقة عملها، ويمكننا الوصول إليها عن طريق الكائن العام process.

نُنشئ ملفًا جديدًا بالاسم environment.js:

nano environment.js

ونكتب داخله الشيفرة التالية ونحفظ الملف:

console.log(process.env);

يحوي الكائن env على متغيرات البيئة المتاحة لحظة تشغيل نود للبرنامج.

ننفذ الآن البرنامج الجديد:

node environment.js

نلاحظ ظهور خرج مشابه للتالي:

{
  SHELL: '/bin/bash',
  SESSION_MANAGER: 'local/hassan-laptop:@/tmp/.ICE-unix/1638,unix/hassan-laptop:/tmp/.ICE-unix/1638',
  WINDOWID: '0',
  QT_ACCESSIBILITY: '1',
  COLORTERM: 'truecolor',
  XDG_CONFIG_DIRS: '/home/hassan/.config/kdedefaults:/etc/xdg/xdg-plasma:/etc/xdg:/usr/share/kubuntu-default-settings/kf5-settings',
  GTK_IM_MODULE: 'ibus',
  LANGUAGE: 'en_US:ar',
  SSH_AGENT_PID: '1427',
  PWD: '/home/hassan/first-program',
  LOGNAME: hassan,
  HOME: '/home/hassan',
  IM_CONFIG_PHASE: '1',
  LANG: 'en_US.UTF-8',
  LESSCLOSE: '/usr/bin/lesspipe %s %s',
  TERM: 'xterm-256color',
  USER: 'hassan',
  PATH: '/home/hassan/.nvm/versions/node/v16.15.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin',
  DBUS_SESSION_BUS_ADDRESS: 'unix:path=/run/user/1000/bus',
  OLDPWD: '/',
  _: '/home/hassan/.nvm/versions/node/v16.15.1/bin/node'
}

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

الخطوة الخامسة - الوصول لمتغير بيئة محدد

تُمثل خصائص الكائن process.env رابطة بين أسماء متغيرات البيئة وقيمها مُخزَّنة كسلاسل نصية، حيث يمكننا الوصول لأي خاصية ضمن الكائن في جافاسكربت بذكر اسمها بين قوسين مربعين.

نفتح الملف environment.js ضمن محرر النصوص ونعدل محتواه:

nano environment.js

نعدل التعليمة الموجودة فيه لتصبح ما يلي ثم نحفظ الملف:

console.log(process.env["HOME"]);

ننفذ البرنامج:

node environment.js

نحصل على خرج كالتالي:

/home/hassan

بدلًا من طباعة الكائن process.env بكل قيمه اخترنا الخاصية HOME فقط منه، والتي تمثل مسار مجلد المستخدم الحالي، وهي نفس القيمة التي يمثلها متغير البيئة ‎$HOME المتوفر في بيئات يونكس، وستلاحظ اختلافًا في خرج هذا البرنامج أيضًا عند تنفيذه لنفس السبب السابق، حيث سيُعرَض مسار مجلد المستخدم الخاص بك.

والآن بعد أن تعلمنا طريقة الوصول لقيمة متغير بيئة محدد، سنطور البرنامج ليسأل المستخدم عن متغير البيئة الذي يريد عرضه.

الخطوة السادسة - جلب متغير بيئة يحدده المستخدم

سنستفيد من إمكانية وصولنا لوسائط سطر الأوامر التي يُمرِّرها المستخدم، مع إمكانية وصولنا لمتغيرات البيئة لإنشاء أداة سطر أوامر بسيطة مهمتها طباعة قيمة متغير بيئة محدد على الشاشة.

نُنشئ ملفًا جديدًا بالاسم echo.js:

nano echo.js

ونكتب داخله الشيفرة التالية ونحفظ الملف:

const args = process.argv.slice(2);
console.log(process.env[args[0]]);

يُخزن السطر الأول من هذا البرنامج جميع الوسائط التي مَرَّرها المستخدم ضمن ثابت يدعى args، ثم يطبع السطر الثاني عند تنفيذه متغير بيئة محدد بحسب قيمة أول عنصر من عناصر الثابت args، أي بحسب أول وسيط مرَّره المستخدم عند تنفيذ البرنامج.

ننفِّذ البرنامج ونمرر له اسم متغير بيئة ما كالتالي:

node echo.js HOME

سيظهر لنا الخرج التالي:

/home/hassan

حُفِظ الوسيط HOME الذي مرَّرناه للبرنامج السابق ضمن المصفوفة args، ثم استخدمناه للعثور على قيمة متغير البيئة المقابل له باستخدام الكائن process.env، وبذلك يصبح بإمكاننا الوصول لقيمة أي متغير بيئة متوفر في النظام، وجرِّب الآن بنفسك وحاول عرض قيم متغيرات البيئة التالية: PWD, USER, PATH.

والآن سنطور البرنامج لعرض عدة متغيرات بيئة معًا يطلبها المستخدم بدلًا من واحد فقط.

الخطوة السابعة - عرض عدة متغيرات بيئة

يمكن للبرنامج الآن في كل مرة عرض متغير بيئة واحد فقط، لذا في هذه الخطوة سنطوره ليستقبل عدد من الوسائط من سطر الأوامر ويعرض متغيرات البيئة المقابلة لها.

نفتح ملف البرنامج echo.js ضمن محرر النصوص:

nano echo.js

ونبدل بمحتواه الشيفرة التالية ثم نحفظ الملف:

const args = process.argv.slice(2);

args.forEach(arg => {
  console.log(process.env[arg]);
});

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

ننفذ البرنامج السابق ونمرر له عدة أسماء لمتغيرات بيئة كالتالي:

node echo.js HOME PWD

لنحصل على الخرج:

/home/hassan
/home/hassan/first-program

نتأكد باستخدامنا للتابع forEach من معالجة كافة الوسائط التي مررها المستخدم للبرنامج، والمُخزنة ضمن الثابت args وطباعة متغير البيئة المقابل لها، وبعد أن أصبح البرنامج الآن يعرض قيم جميع متغيرات البيئة التي يطلبها المستخدم، يجب معالجة الحالة التي يمرر فيها المستخدم متغير بيئة غير موجود.

الخطوة الثامنة - معالجة طلب المستخدم لمتغير بيئة غير موجود

لنحاول طلب عرض قيمة متغير بيئة ما غير موجود من البرنامج ونلاحظ ماذا سيحدث:

node echo.js HOME PWD NOT_DEFINED

نحصل على خرج كالتالي:

/home/hassan
/home/hassan/first-program
undefined

نلاحظ عرض قيمة أول متغيري بيئة في أول سطرين كما هو متوقع، أما في السطر الأخير ظهرت لنا القيمة undefined، وكما نعلم في جافاسكربت القيمة undefined تعني أن الخاصية أو المتغير غير مُعرَّف ولم تُحدد قيمته بعد، وذلك لأن متغير البيئة الذي طلبناه NOT_DEFINED غير موجود لذا طُبعت تلك القيمة عوضًا، وبدلًا من ذلك يمكننا عرض رسالة خطأ للمستخدم تُعلمه أن متغير البيئة الذي يطلبه غير موجود.

نفتح الملف مرة أخرى للتعديل عليه:

nano echo.js

ونضيف الشيفرة التالية:

const args = process.argv.slice(2);

args.forEach(arg => {
  let envVar = process.env[arg];
  if (envVar === undefined) {
    console.error(`Could not find "${arg}" in environment`);
  } else {
    console.log(envVar);
  }
});

ما قمنا به هو تعديل تابع رد النداء المُمرر للتابع forEach ليقوم بالخطوات التالية:

  1. استخراج متغير البيئة للوسيط الحالي وتخزين قيمته في المتغير envVar.
  2. التحقق ما إذا كانت قيمة envVar غير مُعرّفة undefined.
  3. في حال كانت قيمة envVar غير مُعرّفة undefined نطبع رسالة تُعلم المستخدم بعدم وجود متغير بيئة لهذا الوسيط.
  4. في حال عُثر على متغير البيئة نطبع قيمته.

يطبع التابع console.error رسالة على الشاشة من خلال مجرى الخطأ القياسي stderr، بينما يطبع التابع console.log القيم المُمررة له عبر مجرى الخرج القياسي stdout، ولن نلاحظ أي فرق بين استخدام المجريين stdout و stderr عند تنفيذ البرنامج من خلال سطر الأوامر، ويعتبر استخدام كل تابع منهما في حالته الخاصة وتحديدًا طباعة رسائل الخطأ عبر المجرى stderr من الممارسات الجيدة في تطوير البرمجيات، لأنه يُمَكّن البرامج الأخرى من تحديد تلك الأخطاء والتعامل معها إن لزم ذلك.

والآن نعيد تنفيذ البرنامج كالتالي:

node echo.js HOME PWD NOT_DEFINED

لنحصل على الخرج:

/home/hassan
/home/hassan/first-program
Could not find "NOT_DEFINED" in environment

نلاحظ ظهور رسالة للمستخدم تفيد بأن المتغير NOT_DEFINED لم يُعثر عليه.

ختامًا

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

ترجمة -وبتصرف- للمقال How To Write and Run Your First Program in Node.js لصاحبه Stack Abuse.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



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

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

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.


×
×
  • أضف...