سنتعرّف من خلال هذا المقال على وحدات Node.js الأساسية مثل وحدة fs وpath وos وevents وتوابعها المتعددة، كما يمكنك بناء وحدة مخصَّصة بالاعتماد على الوحدات الأساسية، حيث سنتعرّف على كيفية استخدام واجهة module.exports البرمجية لتصدير بياناتك، وسنتعرّف على وحدة MySQL للتعامل مع قواعد البيانات.
وحدة fs
توفّر وحدة fs
عمليات متعددة ومفيدة للوصول إلى نظام الملفات والتفاعل معه، وليست هناك حاجة لتثبيتها نظرًا لكونها جزءًا من نواة نود، إذ يمكن استخدامها ببساطة عن طريق طلبها كما يلي:
const fs = require('fs')
ثم يمكنك الوصول إلى جميع توابعها التي تشمل ما يلي:
-
fs.access()
: يتحقق من وجود الملف ويمكن لنود الوصول إلى الملف باستخدام أذوناته. -
fs.appendFile()
: يُلحِق بيانات بملف، وينشئ الملف إذا كان غير موجود مسبقًا. -
fs.chmod()
: يغيّر أذونات الملف المحدَّد بواسطة اسم الملف المُمرَّر، ويتعلق بالتابعَينfs.lchmod()
وfs.fchmod()
. -
fs.chown()
: يغيّر مالك ومجموعة الملف المحدَّد بواسطة اسم الملف المُمرَّر، ويتعلق بالتابعَينfs.fchown()
وfs.lchown()
. -
fs.close()
: يغلق واصف الملف file descriptor. -
fs.copyFile()
: ينسخ ملفًا. -
fs.createReadStream()
: ينشئ مجرى stream ملف قابل للقراءة. -
fs.createWriteStream()
: ينشئ مجرى ملف قابل للكتابة. -
fs.link()
: ينشئ رابطًا صلبًا hard link جديدًا إلى ملف. -
fs.mkdir()
: ينشئ مجلدًا جديدًا. -
fs.mkdtemp()
: ينشئ مجلدًا مؤقتًا. -
fs.open()
: يضبط نمط الملف. -
fs.readdir()
: يقرأ محتويات مجلد. -
fs.readFile()
: يقرأ محتوى ملف، ويتعلق بالتابعfs.read()
. -
fs.readlink()
: يقرأ قيمة الوصلة الرمزية symbolic link. -
fs.realpath()
: يُستخدَم لربط resolve مؤشرات مسار الملف النسبي (.
و..
) مع المسار الكامل. -
fs.rename()
: يعيد تسمية ملف أو مجلد. -
fs.rmdir()
: يزيل مجلدًا. -
fs.stat()
: يعيد حالة الملف المحدَّد بواسطة اسم الملف المُمرَّر، ويتعلق بالتابعَينfs.fstat()
وfs.lstat()
. -
fs.symlink()
: ينشئ وصلةً رمزيةً جديدًا إلى ملف. -
fs.truncate()
: يقتطع الملف المحدَّد بواسطة اسم الملف المُمرَّر إلى طول معيَّن، ويتعلق بالتابعfs.ftruncate()
. -
fs.unlink()
: يزيل ملفًا أو وصلةً رمزيةً. -
fs.unwatchFile()
: يوقِف مشاهدة التغييرات على ملف. -
fs.utimes()
: يغيّر الطابع الزمني timestamp للملف المحدَّد باسم الملف المُمرَّر، ويتعلق بالتابعfs.futimes()
. -
fs.watchFile()
: يبدأ بمشاهدة التغييرات على ملف، ويتعلق بالتابعfs.watch()
. -
fs.writeFile()
: يكتب بيانات في ملف، ويتعلق بالتابع:fs.write()
.
جميع التوابع في وحدة fs
غير متزامنة افتراضيًا، ولكن يمكنها العمل بطريقة متزامنة من خلال إلحاق الكلمة Sync
باسم التابع كما يلي:
-
fs.rename()
-
fs.renameSync()
-
fs.write()
-
fs.writeSync()
ويحدِث ذلك فرقًا كبيرًا في تدفق تطبيقك.
اقتباستوضيح: تتضمن نود 10 أنواع من الدعم التجريبي لواجهة برمجة تطبيقات قائمة على الوعود promise.
لنختبر التابع fs.rename()
مثلًا، حيث تُستخدَم واجهة برمجة التطبيقات API غير المتزامنة مع دالة رد نداء callback:
const fs = require('fs') fs.rename('before.json', 'after.json', (err) => { if (err) { return console.error(err) } //done })
يمكن استخدام واجهة برمجة تطبيقات متزامنة مثل المثال التالي مع كتلة try/catch لمعالجة الأخطاء:
const fs = require('fs') try { fs.renameSync('before.json', 'after.json') //done } catch (err) { console.error(err) }
الاختلاف الرئيسي هو إيقاف تنفيذ السكربت الخاص بك في المثال الثاني إلى أن تنجح عملية الملف.
للمزيد من المعلومات حول هذه الوحدة، يمكنك الرجوع إلى توثيق التعامل مع نظام الملفات في Node.js في موسوعة حسوب.
وحدة المسار path
توفِّر وحدة path
عمليات متعددة ومفيدة للوصول إلى نظام الملفات والتفاعل معه، وليست هناك حاجة لتثبيتها نظرًا لكونها جزءًا من نواة نود، إذ يمكن استخدامها ببساطة عن طريق طلبها كما يلي:
const path = require('path')
توفِّر هذه الوحدة محرف path.sep
الذي يوفّر فاصل مقاطع المسار path segment separator (\
على نظام ويندوز Windows و/
على نظامي لينكس Linux وmacOS)، بالإضافة إلى محرف path.delimiter
الذي يوفّر محدّد المسار path delimiter (;
على ويندوز Windows و:
على نظامَي لينكس Linux وmacOS).
توابع وحدة path
هي:
-
path.basename()
-
path.dirname()
-
path.extname()
-
path.isAbsolute()
-
path.join()
-
path.normalize()
-
path.parse()
-
path.relative()
-
path.resolve()
للمزيد من المعلومات حول هذه الوحدة، يمكنك الرجوع إلى توثيق وحدة المسار (Path) في Node.js في موسوعة حسوب.
التابع path.basename()
يعيد هذا التابع الجزء الأخير من المسار، ويمكن للمعامِل الثاني تحديد امتداد الملف لإعطاء الملف دون امتداده كما يلي:
require('path').basename('/test/something') //something require('path').basename('/test/something.txt') //something.txt require('path').basename('/test/something.txt', '.txt') //something
التابع path.dirname()
يعيد هذا التابع جزء المجلد أو الدليل من المسار كما يلي:
require('path').dirname('/test/something') // /test require('path').dirname('/test/something/file.txt') // /test/something
التابع path.extname()
يعيد هذا التابع جزء الامتداد من المسار كما يلي:
require('path').dirname('/test/something') // '' require('path').dirname('/test/something/file.txt') // '.txt'
التابع path.isAbsolute()
يعيد هذا التابع القيمة true إذا كان المسار مسارًا مطلقًا.
require('path').isAbsolute('/test/something') // true require('path').isAbsolute('./test/something') // false
التابع path.join()
يربط هذا التابع جزأين أو أكثر من المسار مع بعضها البعض كما يلي:
const name = 'flavio' require('path').join('/', 'users', name, 'notes.txt') //'/users/flavio/notes.txt'
التابع path.normalize()
يحاول هذا التابع حساب المسار الفعلي عندما يحتوي على محددات نسبية مثل .
أو ..
أو شرطات مائلة مزدوجة:
require('path').normalize('/users/flavio/..//test.txt') ///users/test.txt
التابع path.parse()
يوزّع هذا التابع مسارًا على كائن يتكون من أجزاء متعددة هي:
-
root
: يمثّل الجذر. -
dir
: هو مسار المجلد بداية من الجذر. -
base
: يمثّل اسم الملف مع الامتداد. -
name
: هو اسم الملف. -
ext
: يمثّل امتداد الملف.
إليك المثال التالي:
require('path').parse('/users/test.txt')
وتكون النتيجة كما يلي:
{ root: '/', dir: '/users', base: 'test.txt', ext: '.txt', name: 'test' }
التابع path.relative()
يقبل هذا التابع مسارين على أساس وسائط، ويعيد المسار النسبي من المسار الأول إلى المسار الثاني بناءً على مجلد العمل الحالي مثل المثال التالي:
require('path').relative('/Users/flavio', '/Users/flavio/test.txt') //'test.txt' require('path').relative('/Users/flavio', '/Users/flavio/something/test.txt') //'something/test.txt'
التابع path.resolve()
يمكنك حساب المسار المطلق لمسار نسبي باستخدام التابع path.resolve()
كما يلي:
path.resolve('flavio.txt') //'/Users/flavio/flavio.txt' إذا شُغِّل من المجلد المحلي
إذا حدّدت المعامل الثاني، فسيستخدم التابع resolve
المعامِل الأول أساسًا للمعامِل الثاني كما يلي:
path.resolve('tmp', 'flavio.txt') // '/Users/flavio/tmp/flavio.txt' إذا شُغِّل من المجلد المحلي
إذا بدأ المعامِل الأول بشرطة مائلة، فهذا يعني أنه مسار مطلق كما يلي:
path.resolve('/etc', 'flavio.txt')//'/etc/flavio.txt'
وحدة os
توفِّر هذه الوحدة عمليات متعددة يمكنك استخدامها لاسترداد معلومات من نظام التشغيل الأساسي والحاسوب الذي يعمل عليه البرنامج والتفاعل معه.
const os = require('os')
هناك بعض الخاصيات المفيدة التي تخبرنا ببعض الأمور الأساسية المتعلقة بمعالجة الملفات مثل:
-
os.EOL
التي تعطينا متسلسلة محدّد السطور، وهي\n
على نظامَي لينكس Linux وmacOS؛ أما على نظام ويندوز Windows فهي\r\n
.
اقتباستوضيح: نقصد بنظامَي لينكس وmacOS منصات POSIX، واستبعدنا بهدف التبسيط أنظمة التشغيل الأخرى الأقل شيوعًا التي يمكن تشغيل نود Node عليها.
-
os.constants.signals
التي تعطينا كل الثوابت المتعلقة بمعالجة إشارات العمليات مثل SIGHUP وSIGKILL وما إلى ذلك، كما يمكنك الاطلاع على جميع هذه الثوابت على /node_os. -
os.constants.errno
التي تضبط الثوابت في تقارير الخطأ مثل EADDRINUSE وEOVERFLOW وغير ذلك.
لنتعرّف الآن على التوابع الرئيسية التي توفرها وحدة os
وهي:
-
os.arch()
-
os.cpus()
-
os.endianness()
-
os.freemem()
-
os.homedir()
-
os.hostname()
-
os.hostname()
-
os.loadavg()
-
os.networkInterfaces()
-
os.platform()
-
os.release()
-
os.tmpdir()
-
os.totalmem()
-
os.type()
-
os.uptime()
-
os.userInfo()
للمزيد من المعلومات حول هذه الوحدة، يمكنك الرجوع إلى توثيق الوحدة os في Node.js في موسوعة حسوب.
التابع os.arch()
يعيد هذا التابع السلسلة النصية التي تحدد البنية الأساسية مثل arm
وx64
وarm64
.
التابع os.cpus()
يعيد معلومات وحدات المعالجة المركزية المتوفرة على نظامك، وإليك المثال التالي:
[ { model: 'Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz', speed: 2400, times: { user: 281685380, nice: 0, sys: 187986530, idle: 685833750, irq: 0 } }, { model: 'Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz', speed: 2400, times: { user: 282348700, nice: 0, sys: 161800480, idle: 703509470, irq: 0 } } ]
التابع os.endianness()
يعيد هذا التابع القيمة BE
أو القيمة LE
بناءً على طريقة تصريف نود باستخدام تخزين البتات الأقل أهمية أولًا Big Endian أو تخزين البتات الأكثر أهمية أولًا Little Endian.
التابع os.freemem()
يعيد هذا التابع عدد البايتات التي تمثل الذاكرة المتاحة في النظام.
التابع os.homedir()
يعيد هذا التابع المسار إلى مجلد المستخدِم الحالي الرئيسي مثل المثال التالي:
'/Users/flavio'
التابع os.hostname()
يعيد هذا التابع اسم المضيف hostname.
التابع os.loadavg()
يعيد هذا التابع الحساب الذي أجراه نظام التشغيل على متوسط التحميل، حيث يعيد فقط قيمة ذات معنى في نظامَي لينكس Linux وmacOS مثل المثال التالي:
[ 3.68798828125, 4.00244140625, 11.1181640625 ]
التابع os.networkInterfaces()
يعيد هذا التابع تفاصيل واجهات الشبكة المتوفرة على نظامك، وإليك المثال التالي:
{ lo0: [ { address: '127.0.0.1', netmask: '255.0.0.0', family: 'IPv4', mac: 'fe:82:00:00:00:00', internal: true }, { address: '::1', netmask: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', family: 'IPv6', mac: 'fe:82:00:00:00:00', scopeid: 0, internal: true }, { address: 'fe80::1', netmask: 'ffff:ffff:ffff:ffff::', family: 'IPv6', mac: 'fe:82:00:00:00:00', scopeid: 1, internal: true } ], en1: [ { address: 'fe82::9b:8282:d7e6:496e', netmask: 'ffff:ffff:ffff:ffff::', family: 'IPv6', mac: '06:00:00:02:0e:00', scopeid: 5, internal: false }, { address: '192.168.1.38', netmask: '255.255.255.0', family: 'IPv4', mac: '06:00:00:02:0e:00', internal: false } ], utun0: [ { address: 'fe80::2513:72bc:f405:61d0', netmask: 'ffff:ffff:ffff:ffff::', family: 'IPv6', mac: 'fe:80:00:20:00:00', scopeid: 8, internal: false } ] }
التابع os.platform()
يعيد هذا التابع المنصة الذي جرى تصريف نود من أجلها مثل:
-
darwin0
. -
freebsd
. -
linux
. -
openbsd
. -
win32
. - وغيرها الكثير.
التابع os.release()
يعيد هذا التابع سلسلةً نصيةً تحدِّد رقم إصدار نظام التشغيل.
التابع os.tmpdir()
يعيد هذا التابع المسار إلى المجلد المؤقت المعيَّن.
التابع os.totalmem()
يعيد هذا التابع عدد البايتات الذي يمثِّل إجمالي الذاكرة المتوفرة في النظام.
التابع os.type()
يحدّد هذا التابع نظام التشغيل كما يلي:
-
Linux
. -
Darwin
على نظام macOS. -
Windows_NT
على نظام ويندوز.
التابع os.uptime()
يعيد هذا التابع عدد الثواني التي عمل فيها الحاسوب منذ آخر إعادة تشغيل.
التابع os.userInfo()
يعيد معلومات عن المستخدِم الفعّال حاليًا.
وحدة الأحداث events
توفِّر لنا وحدة الأحداث events
الصنف EventEmitter، وتُعَدّ أساسًا للعمل مع الأحداث في نود.
const EventEmitter = require('events') const door = new EventEmitter()
يختبر مستمع الأحداث event listener أحداثه الخاصة ويستخدِم الحدثين التاليين:
-
newListener
عند إضافة المستمع. -
removeListener
عند إزالة المستمع.
سنشرح فيما يلي التوابع المفيدة التالية:
-
emitter.addListener()
-
emitter.emit()
-
emitter.eventNames()
-
emitter.getMaxListeners()
-
emitter.listenerCount()
-
emitter.listeners()
-
emitter.off()
-
emitter.on()
-
emitter.once()
-
emitter.prependListener()
-
emitter.prependOnceListener()
-
emitter.removeAllListeners()
-
emitter.removeListener()
-
emitter.setMaxListeners()
للمزيد من المعلومات حول هذه الوحدة، يمكنك الرجوع إلى توثيق الأحداث في Node.js في موسوعة حسوب.
التابع emitter.addListener()
وهو الاسم البديل للتابع emitter.on()
.
التابع emitter.emit()
يصدر هذا التابع حدثًا، حيث يستدعي بصورة متزامنة كل مستمع حدث بالترتيب الذي سُجِّلت به.
التابع emitter.eventNames()
يعيد هذا التابع مصفوفةً من السلاسل النصية التي تمثِّل الأحداث المُسجَّلة في كائن EventListener الحالي:
door.eventNames()
التابع emitter.getMaxListeners()
يُستخدَم هذا التابع للحصول على الحد الأقصى من المستمعين الذي يمكن إضافته إلى كائن EventListener، حيث يُضبَط هذا العدد افتراضيًا على القيمة 10 ولكن يمكن زيادته أو إنقاصه باستخدام setMaxListeners()
.
door.getMaxListeners()
التابع emitter.listenerCount()
يُستخدَم هذا التابع للحصول على عدد مستمعي الحدث المُمرَّرين على أساس معامِلات كما يلي:
door.listenerCount('open')
التابع emitter.listeners()
يُستخدَم هذا التابع للحصول على مصفوفة مستمعي الحدث المُمرَّرين على أساس معامِلات كما يلي:
door.listeners('open')
التابع emitter.off()
يمثّل هذا التابع الاسم البديل للتابع emitter.removeListener()
المُضاف في الإصدار 10 من نود.
التابع emitter.on()
يضيف هذا التابع دالة رد النداء التي تُستدعَى عند إصدار حدث، ويُستخدَم هذا التابع كما يلي:
door.on('open', () => { console.log('Door was opened') })
التابع emitter.once()
يضيف هذا التابع دالة رد النداء التي تُستدعَى عند إصدار حدث لأول مرة بعد تسجيله، حيث ستُستدعَى دالة رد النداء تلك مرةً واحدةً فقط، ولن تُستدعَى مرةً أخرى.
const EventEmitter = require('events') const ee = new EventEmitter() ee.once('my-event', () => { //ًاستدعِ دالة رد النداء مرةً واحدة })
التابع emitter.prependListener()
يُضاف المستمع الذي تضيفه باستخدام on
أو addListener
في آخر طابور المستمعين ويُستدعَى أخيرًا كذلك، ولكنه يُضاف ويُستدعَى قبل المستمعين الآخرين باستخدام prependListener
.
التابع emitter.prependOnceListener()
يُضاف المستمع الذي تضيفه باستخدام once
في آخر طابور المستمعين ويُستدعَى أخيرًا كذلك، ولكنه يُضاف ويُستدعَى قبل المستمعين الآخرين باستخدام prependOnceListener
.
التابع emitter.removeAllListeners()
يزيل هذا التابع جميع مستمعي الكائن الذي يصدر الأحداث ويستمع إلى حدث محدَّد:
door.removeAllListeners('open')
التابع emitter.removeListener()
يزيل مستمعًا محدَّدًا عن طريق حفظ دالة رد النداء في متغير عند إضافته، بحيث يمكنك الإشارة إليه لاحقًا:
const doSomething = () => {} door.on('open', doSomething) door.removeListener('open', doSomething)
التابع emitter.setMaxListeners()
يضبط الحد الأقصى لعدد المستمعين الذي يمكن إضافته إلى كائن EventListener، حيث يُضبَط هذا العدد افتراضيًا على القيمة 10 ولكن يمكن زيادته أو إنقاصه.
door.setMaxListeners(50)
وحدة HTTP
توفّر وحدة http في Node.js دوالًا وأصنافًا مفيدة لبناء خادم HTTP، وتُعَدّ الوحدة الأساسية لشبكات نود، كما يمكن تضمين وحدة http كما يلي:
const http = require('http')
توفّر وحدة http بعض الخاصيات properties والتوابع methods والأصناف classes.
للمزيد من المعلومات حول هذه الوحدة، يمكنك الرجوع إلى توثيق الوحدة HTTP في Node.js في موسوعة حسوب.
الخاصيات
توفِّر وحدة HTTP الخاصيات التالية:
-
http.METHODS
-
http.STATUS_CODES
-
http.globalAgent
الخاصية http.METHODS
تعطي هذه الخاصية قائمةً بجميع توابع HTTP المدعومة كما يلي:
> require('http').METHODS [ 'ACL', 'BIND', 'CHECKOUT', 'CONNECT', 'COPY', 'DELETE', 'GET', 'HEAD', 'LINK', 'LOCK', 'M-SEARCH', 'MERGE', 'MKACTIVITY', 'MKCALENDAR', 'MKCOL', 'MOVE', 'NOTIFY', 'OPTIONS', 'PATCH', 'POST', 'PROPFIND', 'PROPPATCH', 'PURGE', 'PUT', 'REBIND', 'REPORT', 'SEARCH', 'SUBSCRIBE', 'TRACE', 'UNBIND', 'UNLINK', 'UNLOCK', 'UNSUBSCRIBE' ]
الخاصية http.STATUS_CODES
تعطي هذه الخاصية قائمةً بجميع رموز حالة HTTP ووصفها كما يلي:
> require('http').STATUS_CODES { '100': 'Continue', '101': 'Switching Protocols', '102': 'Processing', '200': 'OK', '201': 'Created', '202': 'Accepted', '203': 'Non-Authoritative Information', '204': 'No Content', '205': 'Reset Content', '206': 'Partial Content', '207': 'Multi-Status', '208': 'Already Reported', '226': 'IM Used', '300': 'Multiple Choices', '301': 'Moved Permanently', '302': 'Found', '303': 'See Other', '304': 'Not Modified', '305': 'Use Proxy', '307': 'Temporary Redirect', '308': 'Permanent Redirect', '400': 'Bad Request', '401': 'Unauthorized', '402': 'Payment Required', '403': 'Forbidden', '404': 'Not Found', '405': 'Method Not Allowed', '406': 'Not Acceptable', '407': 'Proxy Authentication Required', '408': 'Request Timeout', '409': 'Conflict', '410': 'Gone', '411': 'Length Required', '412': 'Precondition Failed', '413': 'Payload Too Large', '414': 'URI Too Long', '415': 'Unsupported Media Type', '416': 'Range Not Satisfiable', '417': 'Expectation Failed', '418': 'I\'m a teapot', '421': 'Misdirected Request', '422': 'Unprocessable Entity', '423': 'Locked', '424': 'Failed Dependency', '425': 'Unordered Collection', '426': 'Upgrade Required', '428': 'Precondition Required', '429': 'Too Many Requests', '431': 'Request Header Fields Too Large', '451': 'Unavailable For Legal Reasons', '500': 'Internal Server Error', '501': 'Not Implemented', '502': 'Bad Gateway', '503': 'Service Unavailable', '504': 'Gateway Timeout', '505': 'HTTP Version Not Supported', '506': 'Variant Also Negotiates', '507': 'Insufficient Storage', '508': 'Loop Detected', '509': 'Bandwidth Limit Exceeded', '510': 'Not Extended', '511': 'Network Authentication Required' }
الخاصية http.globalAgent
تؤشّر هذه الخاصية إلى نسخة كائن الوكيل Agent العامة، والذي هو نسخة من الصنف http.Agent
، حيث يُستخدَم هذا الصنف لإدارة الاتصالات المستمرة وإعادة استخدام عملاء HTTP، وهو المكوّن الأساسي من شبكات HTTP الخاصة بنود Node.
التوابع
توفِّر وحدة HTTP التوابع التالية:
-
http.createServer()
-
http.request()
-
http.get()
التابع http.createServer()
يعيد هذا التابع نسخةً جديدةً من الصنف http.Server
، حيث يُستخدَم كما يلي:
const server = http.createServer((req, res) => { //معالجة كل طلب باستخدام دالة رد النداء هذه })
التابع http.request()
ينشئ طلب HTTP إلى خادم، مما يؤدي إلى إنشاء نسخة من الصنف http.ClientRequest
.
التابع http.get()
يشبه التابع http.request()
، ولكنه يضبط تلقائيًا تابع HTTP على GET ويستدعي التابع req.end()
تلقائيًا.
الأصناف Classes
توفِّر وحدة HTTP خمسة أصناف هي:
-
http.Agent
-
http.ClientRequest
-
http.Server
-
http.ServerResponse
-
http.IncomingMessage
الصنف http.Agent
نُنشئ نود نسخةً عامةً من الصنف http.Agent
لإدارة الاتصالات المستمرة وإعادة استخدام عملاء HTTP، وهو المكوّن الأساسي من شبكات HTTP الخاصة بنود Node، كما يتأكّد هذا الكائن من وضع كل طلب إلى الخادم في طابور ومن إعادة استخدام المقبس socket، كما أنه يحتفظ بمجمّع من المقابس بهدف تحسين الأداء.
الصنف http.ClientRequest
يُنشَأ الكائن http.ClientRequest
عند استدعاء التابع http.request()
أو التابع http.get()
، حيث يُستدعَى حدث response
مع الاستجابة عند تلقيها باستخدام نسخة من كائن http.IncomingMessage
على أساس وسيط، ويمكن قراءة بيانات الاستجابة المُعادة بطريقتين هما:
-
استدعاء التابع
response.read()
. -
يمكنك إعداد مستمعٍ للحدث
data
في معالج الحدثresponse
بحيث يمكنك الاستماع للبيانات المتدفقة إليه.
الصنف http.Server
تُنشَأ وتُعاد عادةً نسخة من هذا الصنف عند إنشاء خادم جديد باستخدام التابع http.createServer()
، يمكنك الوصول إلى توابع كائن خادم بعد إنشائه، وهذه التوابع هي:
-
close()
الذي يوقِف الخادم من قبول اتصالات جديدة. -
listen()
الذي يشغّل خادم HTTP ويستمع للاتصالات.
الصنف http.ServerResponse
ينشئه الصنف http.Server
ويمرّره على أساس معامل ثانٍ لحدث request
الذي يشغّله، حيث يُعرَف هذا الصنف ويُستخدَم في الشيفرة على أنه كائن res
كما يلي:
const server = http.createServer((req, res) => { //res هو كائن http.ServerResponse })
التابع الذي ستستدعيه دائمًا في المعالج هو end()
والذي يغلق الاستجابة بعد اكتمال الرسالة ثم يستطيع الخادم إرسالها إلى العميل، إذ يجب استدعاؤه في كل استجابة، وتُستخدَم التوابع التالية للتفاعل مع ترويسات HTTP:
-
getHeaderNames()
: للحصول على قائمة بأسماء ترويسات HTTP المضبوطة مسبقًا. -
getHeaders()
: للحصول على نسخة من ترويسات HTTP المضبوطة مسبقًا. -
setHeader('headername', value)
: يحدّد قيمة ترويسة HTTP. -
getHeader('headername')
: للحصول على ترويسة HTTP المضبوطة مسبقًا. -
removeHeader('headername')
: يزيل ترويسة HTTP المضبوطة مسبقًا. -
hasHeader('headername')
: يعيد القيمة true إذا احتوت الاستجابة على هذه الترويسة المضبوطة. -
headersSent()
: يعيد القيمة true إذا أُرسِلت الترويسات إلى العميل. مسبقًا
يمكنك إرسال الترويسات بعد معالجتها إلى العميل عن طريق استدعاء التابع response.writeHead()
الذي يقبل رمز الحالة statusCode على أساس معامل أول، ورسالة الحالة الاختيارية، وكائن الترويسات، كما يمكنك إرسال البيانات إلى العميل في جسم الاستجابة عن طريق استخدام التابع write()
الذي سيرسل البيانات المخزَّنة إلى مجرى استجابة HTTP، فإذا لم تُرسَل الترويسات بعد باستخدام التابع response.writeHead()
، فستُرسَل الترويسات أولًا مع رمز الحالة والرسالة المحدَّدة في الطلب والتي يمكنك تعديلها عن طريق ضبط قيم الخاصيات statusCode
وstatusMessage
كما يلي:
response.statusCode = 500 response.statusMessage = 'Internal Server Error'
الصنف http.IncomingMessage
يُنشَأ كائن http.IncomingMessage
باستخدام:
-
http.Server
عند الاستماع إلى الحدثrequest
. -
http.ClientRequest
عند الاستماع إلى الحدثresponse
.
يمكن استخدام كائن http.IncomingMessage
للوصول إلى خاصيات الاستجابة التالية:
-
الحالة status باستخدام توابع
statusCode
وstatusMessage
الخاصة به. -
الترويسات باستخدام توابع
headers
أوrawHeaders
الخاصة به. -
تابع HTTP باستخدام تابع
method
الخاص به. -
إصدار HTTP باستخدام تابع
httpVersion
. -
عنوان URL باستخدام تابع
url
. -
المقبس الأساسي underlying socket باستخدام تابع
socket
.
يمكن الوصول إلى البيانات باستخدام المجاري streams، حيث ينفّذ كائن http.IncomingMessage
واجهة المجرى Stream القابلة للقراءة.
وحدة MySQL
تُعَدّ MySQL واحدةً من أكثر قواعد البيانات العلائقية شيوعًا في العالم، إذ يحتوي نظام نود Node المجتمعي على حزم مختلفة تتيح لك التعامل مع MySQL وتخزين البيانات واسترداد البيانات وما إلى ذلك، كما سنستخدِم حزمة mysqljs/mysql التي تحتوي على أكثر من 12000 نجمة على GitHub وهي موجودة منذ سنوات.
تثبيت حزمة نود mysql
يمكنك تثبيتها باستخدام الأمر التالي:
npm install mysql
تهيئة الاتصال بقاعدة البيانات
يجب تضمين الحزمة أولًا كما يلي:
const mysql = require('mysql')
ثم تنشئ اتصالًا كما يلي:
const options = { user: 'the_mysql_user_name', password: 'the_mysql_user_password', database: 'the_mysql_database_name' } const connection = mysql.createConnection(options)
ثم تهيئ اتصالًا جديدًا عن طريق استدعاء ما يلي:
connection.connect(err => { if (err) { console.error('An error occurred while connecting to the DB') throw err } })
خيارات الاتصال
احتوى كائن options
في المثال السابق على 3 خيارات هي:
const options = { user: 'the_mysql_user_name', password: 'the_mysql_user_password', database: 'the_mysql_database_name' }
هناك خيارات أخرى متعددة يمكنك استخدامها مثل:
-
host
: اسم مضيف قاعدة البيانات، وقيمته الافتراضية هيlocalhost
. -
port
رقم منفذ خادم MySQL، وقيمته الافتراضية هي 3306. -
socketPath
: يُستخدَم لتحديد مقبس يونيكس unix بدلًا منhost
وport
. -
debug
: يمكن استخدامه لتنقيح الأخطاء debugging عند تعطيله افتراضيًا. -
trace
: يطبع تعقبات المكدس stack traces عند حدوث الأخطاء عند تفعيله افتراضيًا. -
ssl
: يُستخدَم لإعداد اتصال SSL إلى الخادم.
إجراء استعلام SELECT
أصبحتَ الآن جاهزًا لإجراء استعلام SQL في قاعدة البيانات، وسيستدعي الاستعلامُ بمجرد تنفيذه دالةَ رد النداء التي تحتوي على الخطأ المُحتمَل error والنتائج results والحقول fields كما يلي:
connection.query('SELECT * FROM todos', (error, todos, fields) => { if (error) { console.error('An error occurred while executing the query') throw error } console.log(todos) })
يمكنك تمرير القيم التي ستُتجاوز تلقائيًا كما يلي:
const id = 223 connection.query('SELECT * FROM todos WHERE id = ?', [id], (error, todos, fields) => { if (error) { console.error('An error occurred while executing the query') throw error } console.log(todos) })
يمكنك تمرير قيم متعددة من خلال وضع مزيد من العناصر في المصفوفة التي تمررها على أساس معامل ثانٍ كما يلي:
const id = 223 const author = 'Flavio' connection.query('SELECT * FROM todos WHERE id = ? AND author = ?', [id, author], (error, todos, fields) => { if (error) { console.error('An error occurred while executing the query') throw error } console.log(todos) })
إجراء استعلام INSERT
يمكنك تمرير كائن كما يلي:
const todo = { thing: 'Buy the milk' author: 'Flavio' } connection.query('INSERT INTO todos SET ?', todo, (error, results, fields) => { if (error) { console.error('An error occurred while executing the query') throw error } })
إذا احتوى الجدول على مفتاح رئيسي primary key مع auto_increment
، فستُعاد قيمته ضمن القيمة results.insertId
كما يلي:
const todo = { thing: 'Buy the milk' author: 'Flavio' } connection.query('INSERT INTO todos SET ?', todo, (error, results, fields) => { if (error) { console.error('An error occurred while executing the query') throw error }} const id = results.resultId console.log(id) )
إغلاق الاتصال
يمكنك استدعاء التابع end()
عند إنهاء الاتصال بقاعدة البيانات كما يلي:
connection.end()
يعمل ذلك على التأكد من إرسال أي استعلام مُعلَّق وإنهاء الاتصال بأمان.
وحدات مخصصة
إذا لم تعثر على الوحدات المناسبة لك ضمن الوحدات الأساسية، فيمكنك بناء وحدة مخصَّصة تخدم غرضك بالاعتماد على الوحدات الأساسية ويمكنك أن تصدِّرها وتستوردها حتى أنه يمكنك بناء مكتبة كاملة، حيث سنتعرّف فيما يلي على كيفية استخدام واجهة module.exports البرمجية لتصدير بياناتك إلى ملفات أخرى في تطبيقك أو إلى تطبيقات أخرى.
يمتلك نود نظام وحدات مبنيّ مسبقًا، إذ يمكن لملف Node.js استيراد العمليات التي تصدّرها ملفات Node.js الأخرى، فإذا أردت استيراد شيءٍ ما، فاستخدم ما يلي لاستيراد العمليات الظاهرة في ملف library.js
الموجود في مجلد الملف الحالي، إذ يجب إظهار العمليات في هذا الملف قبل أن تستوردها ملفات أخرى:
const library = require('./library')
يكون أيّ كائن أو متغير آخر مُعرَّف في الملف خاصًا private افتراضيًا ولا يظهر لأيّ شيء خارجي، وهذا ما تسمح لنا به واجهة برمجة تطبيقات module.exports
التي يوفِّرها [نظام module](https://nodejs.org/api/modules.html
)، وإذا أسندتَ كائنًا أو دالةً مثل خاصية exports
جديدة، فهذا هو الشيء الذي يظهر، ويمكن استيراده على هذا النحو في أجزاء أخرى من تطبيقك أو في تطبيقات أخرى أيضًا، حيث يمكنك تطبيق ذلك بطريقتين، الأولى هي إسناد كائن لوحدة module.exports
، وهو كائن خارجي يوفّره نظام module، وبالتالي سيصدّر ملفك هذا الكائن فقط:
const car = { brand: 'Ford', model: 'Fiesta' } module.exports = car //في الملف الآخر.. const car = require('./car')
أما الطريقة الثانية فهي إضافة الكائن المُصدَّر على أساس خاصية exports
، حيث تتيح لك هذه الطريقة تصدير كائنات أو دوال أو بيانات متعددة:
const car = { brand: 'Ford', model: 'Fiesta' } exports.car = car
أو مباشرةً:
const car = { brand: 'Ford', model: 'Fiesta' }
كما ستستخدمه في الملف الآخر من خلال الإشارة إلى خاصية الاستيراد كما يلي:
const items = require('./items') items.car
أو كما يلي:
const car = require('./items').car
هناك فرق بين module.exports
وexports
، فالأول يُظهِر الكائن الذي يؤشّر إليه، بينما يُظهِر الثاني خاصيات الكائن الذي يؤشّر إليه.
ترجمة -وبتصرّف- للفصل Some essential core modules من كتاب The Node.js handbook لصاحبه Flavio Copes.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.