تعلم Node.js من الصفر
تتيح Node.js تشغيل JavaScript خارج المتصفح، على الحاسوب وعلى الخوادم. يمكنك استخدام لغة واحدة في الواجهة الأمامية والخلفية معًا. تعتمد Node.js على الإدخال والإخراج غير المانع (non-blocking I/O)، لذلك تناسب عمليات الشبكات وواجهات البرمجة. تشغّل هذه المقالة أول سكربت، وتقرأ الملفات وتكتبها بالوحدات القياسية، وتبني خادم HTTP صغيرًا يرد بصيغة JSON.
جميع الأمثلة في هذه المقالة تم تشغيلها باستخدام Node.js، والمخرجات المعروضة حقيقية.
ما الذي تحتاجه
- Node.js الإصدار 18 أو أحدث (تحقق بالأمر `node --version`)
- محرر نصوص مثل VS Code
طريقة العمل
أول سكربت
أنشئ الملف `hello.js` وشغّله بالأمر `node hello.js`:
console.log("สวัสดี Node.js");
الوحدات وقراءة الملفات وكتابتها
تأتي Node.js بوحدات قياسية جاهزة مثل `fs` للملفات و`path` للمسارات. يكتب المثال التالي ملف JSON ثم يقرأه مجددًا.
const http = require("http");
const path = require("path");
const fs = require("fs");
// โมดูลและฟังก์ชัน
function grade(score) {
if (score >= 80) return "A";
if (score >= 70) return "B";
if (score >= 50) return "C";
return "F";
}
const students = [
{ name: "สมชาย", score: 85 },
{ name: "สมหญิง", score: 72 },
{ name: "สมศักดิ์", score: 45 },
];
// เขียนไฟล์แล้วอ่านกลับมา
const file = path.join(__dirname, "grades.json");
fs.writeFileSync(file, JSON.stringify(students.map(s => ({ ...s, grade: grade(s.score) })), null, 2));
const data = JSON.parse(fs.readFileSync(file, "utf8"));
console.log("สวัสดี Node.js", data.length, "คน");
console.log(data.map(d => `${d.name}: ${d.grade}`).join("\n"));
// เซิร์ฟเวอร์ HTTP ขนาดเล็ก ตอบ JSON แล้วปิดตัวเองหลังตอบ 1 ครั้ง (สำหรับทดสอบ)
const server = http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8" });
res.end(JSON.stringify({ message: "สวัสดีจาก Node.js", count: data.length }));
server.close();
});
server.listen(3100, () => console.log("server listening on http://localhost:3100"));
المخرجات الفعلية (شغّل السكربت ثم أرسل طلبًا بالأمر curl إلى `http://localhost:3100/`):
สวัสดี Node.js 3 คน
สมชาย: A
สมหญิง: B
สมศักดิ์: F
server listening on http://localhost:3100
{"message":"สวัสดีจาก Node.js","count":3}
لاحظ ما يلي:
- تحمّل `require` الوحدات، و`__dirname` هو مجلد ملف السكربت.
- الدالتان `fs.writeFileSync` و`fs.readFileSync` متزامنتان وتوقفان التنفيذ حتى الانتهاء. هذا مناسب للسكربتات الصغيرة، أما الخوادم فينبغي أن تستخدم الإصدارات غير المتزامنة مثل `fs.promises.readFile`.
- يُنفَّذ الاستدعاء الممرر إلى `http.createServer` عند كل طلب يصل.
Promise وasync/await
تسمح قراءة الملفات بشكل غير متزامن للبرنامج بمتابعة العمل أثناء الانتظار. يستخدم هذا المثال `async/await` ليُقرأ الكود بالترتيب:
const fs = require("fs/promises");
async function main() {
await fs.writeFile("note.txt", "บันทึกจาก Node.js");
const text = await fs.readFile("note.txt", "utf8");
console.log("อ่านได้:", text);
}
main().catch(err => console.error("เกิดข้อผิดพลาด:", err.message));
أخطاء شائعة
- **المنفذ مستخدم بالفعل:** غيّر رقم المنفذ، أو أوقف البرنامج الذي يستخدمه.
- **نسيان `await` مع Promise:** تحصل على الـ Promise نفسه لا على نتيجته.
- **استخدام `require` في ملف ES Module دون إعداد:** تحقق من نوع الوحدة في `package.json`.
- **عدم معالجة الأخطاء:** استخدم `try/catch` أو `.catch` ليُظهر البرنامج سبب الخطأ.
الخطوات التالية
ابنِ واجهة برمجية تحفظ قائمة مهام في ملف JSON، ثم تعلّم Express أو Fastify، وهما إطاران شائعان لـ Node.js.
الخلاصة
تجعل Node.js لغة JavaScript تعمل على الخادم. تتولى الوحدات القياسية الملفات والشبكات، ويُبقي async/await الكود المتزامن قابلًا للقراءة.