NodeJS: بداية سريعة



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

محاضر - ألكسندر كورجيكوف ، مهندس تكنولوجيا المعلومات في مجموعة ING (هولندا).






بضع كلمات حول Node.js


Node.js هو وقت تشغيل جافا سكريبت غير متزامن يعتمد على مفاهيم مثل حلقة الحدث والبنية الموجهة نحو الحدث. تتيح لك منصة Node.js ومدير حزم NPM القياسي إنشاء تطبيقات فعالة لمختلف مجالات الموضوعات - من الويب إلى التعلم الآلي.

أبسط مثال لخادم الويب ( node server.js):

const http = require('http')
const hostname = '127.0.0.1'
const port = 3000
const server = http.createServer((req, res) => {
res.statusCode = 200
res.setHeader('Content-Type', 'text/plain')
res.end('Hello World\n')
})
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`)
})

بالنظر إلى الرمز أعلاه ، يمكن ملاحظة الميزات التالية لـ Node.js:

  1. يمكننا تشغيل كود JavaScript مباشرة على الخادم ، أي أنه من الممكن تنفيذ ملفات JavaScript باستخدام الأمر node.
  2. يتم دعم تنسيق CommonJS للوحدات النمطية لتحميل التبعيات ووحدات ES ، ويمكن استخدام كلا التنسيقين.
  3. يتم دعم مكتبة الوحدة النمطية القياسية ، والتي تعد HTTP جزءًا منها.
  4. تعتمد واجهة برمجة التطبيقات (API) على نمط الاستدعاءات غير المتزامنة ، ولكن يتم دعم Promise أيضًا.
  5. بناء الجملة ES2015 مدعوم. بالمناسبة ، هنا رابط مفيد يمكنك من خلاله الاطلاع دائمًا على إصدار Node الذي تدعم ميزات JS . إذا حدث خطأ ما ، يمكنك مقارنة وفهم المشكلة.

لا تفوت أيضًا الإصدار التجريبي الصغير (VSCode + Chrome Debug).

رحلة قصيرة في التاريخ


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

يستخدم Node.js محرك Chromium بداخله ، أو بالأحرى ذلك الجزء منه الذي يفسر JavaScript - V8 . نظرًا لحقيقة فصل المترجم في وقت واحد إلى مشروع V8 منفصل ، أصبح من الممكن ببساطة إنشاء نظام بيئي حوله. بالمعنى الدقيق للكلمة ، هذا بالضبط ما فعله خالق Node.js Ryan Dahl. بالمناسبة ، توجد اليوم مؤسسة Node.js ، وهي منظمة تدعم المشروع.



بناء


أولاً ، تمت كتابة المكتبة بلغة C ++ و JavaScript. يقع المشروع نفسه على GitHub ، لذلك إذا كنت مهتمًا ، يمكنك التعرف على شفرة المصدر الخاصة به. يمكنك الخوض في دراستها لفترة طويلة جدًا)).

ثانيًا ، كما ذكرنا سابقًا ، فإنه يتضمن V8 (منصة تنفيذ JavaScript من Google) و libuv كجزء من حلقة الأحداث (حلقة الأحداث غير المتزامنة).

حسنًا ، بالطبع ، هناك وحدات مختلفة للعمل مع نظام التشغيل تسمح لك بأداء مهام العمل التي تحتاجها.

من الجدير بالذكر أيضًا أنماط التصميم الرئيسية الشائعة الاستخدام في Node.js:

  • رد الاتصال (سبق ذكره) ؛
  • المراقب (نمط الحدث الأبسط) ؛
  • الوحدة النمطية (على الرغم من أنها منظمة الآن بلغة جافا سكريبت نفسها ، إلا أنها لا تزال ذات صلة في Node.js) ؛
  • المفاعل (نمط التفاعل غير المتزامن مع بعض الموارد عندما لا تحظر الدفق الرئيسي من التعليمات البرمجية). هذا النمط مألوف لمطوري JS. على سبيل المثال ، إذا عملنا في متصفح وكتبنا واجهة أمامية ، فإننا لا نحظر جميع أعمال المتصفح ، ولكن ببساطة الاشتراك في الأحداث من المستخدم ، وعندما يحدث الحدث (بعد "نقرة" ، "دخول" ، إلخ) ، نقوم بتنفيذ رمزنا.

بالمناسبة ، إليك بعض المنافسة التي أجريناها على الويبينار)). والمضي قدما.

وحدات توزيع العقدة القياسية




هل تعرف الوحدات المضمنة في توزيع العقدة القياسي؟ أي أننا نتحدث عن وحدات مضمنة بالفعل ، وبالتالي لا يمكن تثبيتها. بشكل عام ، هناك حوالي 50 منهم ، دعنا نذكر أهمها. لسهولة الإدراك ، نقسمها بشكل تقليدي إلى 5 نقاط:

1. الرئيسية (للعمليات العادية):

  • خ.
  • الموقتات
  • تيارات (للعمل مع تيارات).

2. المرافق:

  • المسار (للعمل مع المسارات) ؛
  • استخدام ؛
  • zlib (الأرشفة وفك الضغط) ؛
  • التشفير (لوظائف التشفير).

3. العمليات (كل ما يتعلق بمعالجة متعددة والتوازي):

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

4. البروتوكولات (جميع أنواع البروتوكولات):

  • http (s) ؛
  • شبكة؛
  • نظام أسماء النطاقات.

5. النظام (على التوالي ، وحدات النظام ، بما في ذلك التصحيح):

  • نظام التشغيل
  • الإصدار 8 ؛
  • async_hooks ؛
  • perf_hooks ؛
  • تتبع الأحداث

ماذا تضيف:

- كائن كروي - تناظرية النافذة ؛
- جميع كائنات JavaScript المتاحة في المتصفح متاحة أيضًا في Node.js ؛
- المهلات - كما هو الحال في المتصفح ؛
- العملية - تمثيل العملية الحالية ؛
- وحدة التحكم متاحة.

الاسترجاعات


رد الاتصال - وظيفة تم تمريرها كوسيطة للرمز ، والتي تنطوي على تنفيذها في وقت ما. بالمناسبة ، نادرًا ما يعتقد الناس أن تنفيذها يمكن أن يكون متزامنًا أو غير متزامن.

const server = http.createServer((req, res) => {
res.statusCode = 200
res.setHeader('Content-Type', 'text/plain')
res.end('Hello World\n')
})
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`)
})

في العقدة ، بشكل افتراضي ، يتم تنفيذ رد الاتصال مع "خطأ" والنتيجة غير متزامنة:

fs.readFile('/etc/passwd', (err, data) => {
if (err) throw err
console.log(data)
})

وإليك ما يبدو عليه مضاد - مثال جيد لكيفية استخدام رد الاتصال بشكل غير صحيح. كما يقولون ، Callback Hell الكلاسيكية :

fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
})

دعنا الآن نرى كيفية إنشاء خادم ويب بسيط وتقديم فهرس HTML كرد على العميل:

const http = require('http')
const server = http.createServer((req, res) => {
res.statusCode = 200
res.setHeader('Content-Type', 'text/plain')
res.end('Hello World\n')
})

لقراءة ملف html المحلي:

const fs = require('fs')
fs.readFile('./index.html', (err, text) => {
console.log(text)
})

بعد الانتهاء من موضوع الاستدعاءات ، أود أن أذكر أنواع الاستدعاء. هناك عمليات رد تقوم بإرجاع خطأ فقط إذا كان هناك خطأ:

fs.access('/etc/passwd', fs.constants.R_OK, (err) => {
console.log(err ? 'no access!' : 'read')
})

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

util.promisify()
fs.promises.*

نوع الإرجاع:

http.request('https://example.com', (error, response, body) => {
...
})

عقدة سؤال وجواب


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

import express from "express";
const app = express();
const port = 3000;
app.get("/", (req, res) => {
res.send("Hello World!");
});
app.listen(port, () => {
console.log(`Example app listening
});



حسنًا ، يمكنك الآن محاولة إنشاء خادم ويب باستخدام مولد سريع بنفسك :

  • استخدام اليشم ، جلسة ملفات تعريف الارتباط ؛
  • جعل تسجيل دخول ساذج.

أو مجرد إلقاء نظرة على كيفية قيام المعلم بذلك ، الذي أعد الحل الجاهز في TypeScript.

هذا كل شئ. أخيرًا - زوجان من الروابط المفيدة:


ونراكم في الدورة .

All Articles