جاوا اسکریپت در سمت سرور (Node.js)
JavaScript خارج از مرورگر، Node.js Runtime، ماژولهای File System و Path و HTTP، Events و Streams و Buffers، Process و Environment Variables و ساخت REST API.
JavaScript خارج از مرورگر
Node.js جاوا اسکریپت را از مرورگر به سرور، ابزار خط فرمان و دسکتاپ برد:
// محیطهای اجرای JS:
// - مرورگر (Chrome, Firefox) → DOM، window
// - Node.js → fs، http، process
// - Deno / Bun → مدرنتر
// تفاوتهای کلیدی Node:
// ✗ window, document, alert
// ✓ require/import, process, __dirname
// ✓ فایلسیستم، شبکه، دیتابیس
Node.js Runtime
موتور V8 + APIهای سیستمی:
// بررسی نسخه:
// node --version
// اجرای فایل:
// node app.js
// REPL تعاملی:
// node
// > 2 + 2
// 4
// globals مخصوص Node:
console.log(__dirname); // پوشه فایل فعلی
console.log(__filename); // مسیر کامل فایل
console.log(process.version);
console.log(process.platform); // win32 / linux
File System — فایلسیستم
const fs = require("node:fs");
// خواندن همگام — блокکننده:
const data = fs.readFileSync("file.txt", "utf8");
console.log(data);
// خواندن ناهمگام — Callback:
fs.readFile("file.txt", "utf8", (err, data) => {
if (err) throw err;
console.log(data);
});
// ناهمگام — Promise (توصیهشده):
const fsPromises = require("node:fs/promises");
async function readFile() {
try {
const data = await fsPromises.readFile("file.txt", "utf8");
console.log(data);
} catch (err) {
console.error("خطا:", err.message);
}
}
// نوشتن:
await fsPromises.writeFile("output.txt", "سلام دنیا");
await fsPromises.appendFile("log.txt", "لاگ جدید\n");
// سایر عملیات:
const stats = await fsPromises.stat("file.txt");
console.log(stats.size, stats.isFile());
await fsPromises.mkdir("new-folder", { recursive: true });
await fsPromises.copyFile("a.txt", "b.txt");
await fsPromises.rename("old.txt", "new.txt");
await fsPromises.unlink("delete.txt"); // حذف
await fsPromises.rm("folder", { recursive: true }); // حذف پوشه
Path — مسیرها
const path = require("node:path");
// join — ساخت امن (چند-پلتفرمی):
const filePath = path.join("folder", "sub", "file.txt");
console.log(filePath); // folder\sub\file.txt (ویندوز)
// resolve — مسیر مطلق:
console.log(path.resolve("data", "db.json"));
// C:\project\data\db.json
// اجزا:
console.log(path.parse("/users/ali/file.txt"));
// { dir: "/users/ali", base: "file.txt",
// ext: ".txt", name: "file" }
console.log(path.extname("photo.jpg")); // .jpg
console.log(path.basename("/a/b/c.txt")); // c.txt
console.log(path.dirname("/a/b/c.txt")); // /a/b
// __dirname + path:
const configPath = path.join(__dirname, "config.json");
HTTP Server — سرور وب
const http = require("node:http");
// سرور ساده:
const server = http.createServer((req, res) => {
// req — درخواست:
console.log(req.method); // GET / POST
console.log(req.url); // /api/users
// res — پاسخ:
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ message: "سلام" }));
});
server.listen(3000, () => {
console.log("سرور روی پورت 3000");
});
// مسیریابی دستی:
const server2 = http.createServer((req, res) => {
if (req.method === "GET" && req.url === "/") {
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
res.end("<h1>صفحه اصلی</h1>");
} else if (req.method === "GET" && req.url === "/api/users") {
const users = [{ id: 1, name: "علی" }];
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify(users));
} else {
res.writeHead(404);
res.end("یافت نشد");
}
});
Events — رویدادها در Node
const EventEmitter = require("node:events");
// ساخت ایمتر:
const emitter = new EventEmitter();
// شنیدن:
emitter.on("greet", (name) => {
console.log(`سلام ${name}!`);
});
// فقط یکبار:
emitter.once("init", () => console.log("شروع"));
// پرتاب:
emitter.emit("greet", "علی"); // سلام علی!
emitter.emit("greet", "سارا"); // سلام سارا!
emitter.emit("init"); // شروع
emitter.emit("init"); // سکوت — once!
// حذف:
const handler = () => console.log("هندلر");
emitter.on("x", handler);
emitter.off("x", handler);
// کلاس سفارشی:
class Database extends EventEmitter {
connect() {
this.emit("connected");
}
}
Streams — جریان داده
پردازش داده قطعهبهقطعه بدون بارگذاری کامل:
const fs = require("node:fs");
// مشکل — کل فایل ۲GB در حافظه: ❌
const data = fs.readFileSync("video.mp4");
// راهحل — Stream: ✓
const readStream = fs.createReadStream("big-file.txt", "utf8");
readStream.on("data", (chunk) => {
console.log("قطعه جدید:", chunk.length, "کاراکتر");
});
readStream.on("end", () => console.log("تمام شد"));
readStream.on("error", (err) => console.error(err));
// کپی با pipe — ساده:
const reader = fs.createReadStream("source.txt");
const writer = fs.createWriteStream("dest.txt");
reader.pipe(writer); // خودکار جریان!
Buffers — بافرهای Node
// Buffer — داده باینری در Node:
const buf = Buffer.from("سلام", "utf8");
console.log(buf); // <Buffer d8 b3 ...>
console.log(buf.length); // 8 بایت
console.log(buf.toString("utf8")); // سلام
// ساخت با طول مشخص:
const buf2 = Buffer.alloc(16); // صفرها
const buf3 = Buffer.allocUnsafe(16); // بدون پاکسازی — سریع
// نوشتن و خواندن:
buf2.write("Hello");
console.log(buf2.toString());
// تبدیل:
const str = Buffer.from("base64-data", "base64").toString("utf8");
const b64 = Buffer.from("متن").toString("base64");
Process — فرآیند
// اطلاعات:
console.log(process.pid); // شناسه فرآیند
console.log(process.cwd()); // پوشه فعلی
console.log(process.platform); // win32
// آرگومانهای خط فرمان:
// node app.js --port 3000
console.log(process.argv);
// [node, app.js, --port, 3000]
// پارس آرگومان:
const args = process.argv.slice(2);
const portIdx = args.indexOf("--port");
const port = portIdx > -1 ? args[portIdx + 1] : 3000;
// env — متغیرهای محیطی:
console.log(process.env.HOME);
console.log(process.env.NODE_ENV); // development/production
// خروج:
process.exit(0); // موفق
process.exit(1); // خطا
// رویداد خروج:
process.on("exit", (code) => {
console.log("خروج با کد:", code);
});
// خطای گرفتهنشده:
process.on("uncaughtException", (err) => {
console.error("خطای مهلک:", err);
process.exit(1);
});
Environment Variables
// تنظیم — خط فرمان:
// set PORT=3000 (ویندوز)
// PORT=3000 node app (لینوکس)
// خواندن:
const PORT = process.env.PORT || 3000;
// فایل .env + dotenv:
// npm install dotenv
require("dotenv").config();
// حالا از .env خوانده میشود:
const dbUrl = process.env.DATABASE_URL;
// .env:
// PORT=3000
// DATABASE_URL=mongodb://localhost:27017/app
// JWT_SECRET=mysecret
// ⚠️ .env در .gitignore!
Timers در Node
// همان مرورگر + نسخه Node:
setTimeout(() => console.log("بعد از ۱ ثانیه"), 1000);
setInterval(() => console.log("هر ثانیه"), 1000);
// مخصوص Node:
setImmediate(() => {
console.log("بعد از عملیات I/O فعلی");
});
process.nextTick(() => {
console.log("قبل از هر چیز دیگر");
});
// ترتیب:
process.nextTick(() => console.log("1 — nextTick"));
setImmediate(() => console.log("2 — immediate"));
setTimeout(() => console.log("3 — timeout"), 0);
// معمولاً: 1 → 3 → 2
ساخت REST API کامل
const http = require("node:http");
const fs = require("node:fs/promises");
const path = require("node:path");
// دیتابیس ساده — فایل JSON:
const DB_FILE = path.join(__dirname, "db.json");
async function readDB() {
try {
const data = await fs.readFile(DB_FILE, "utf8");
return JSON.parse(data);
} catch {
return { users: [] };
}
}
async function writeDB(db) {
await fs.writeFile(DB_FILE, JSON.stringify(db, null, 2));
}
// سرور:
const server = http.createServer(async (req, res) => {
const url = new URL(req.url, `http://${req.headers.host}`);
const json = (code, data) => {
res.writeHead(code, { "Content-Type": "application/json" });
res.end(JSON.stringify(data));
};
try {
// GET /api/users:
if (req.method === "GET" && url.pathname === "/api/users") {
const db = await readDB();
return json(200, db.users);
}
// POST /api/users:
if (req.method === "POST" && url.pathname === "/api/users") {
let body = "";
for await (const chunk of req) body += chunk;
const userData = JSON.parse(body);
if (!userData.name) {
return json(422, { error: "نام الزامی است" });
}
const db = await readDB();
const user = {
id: Date.now(),
name: userData.name,
email: userData.email || null
};
db.users.push(user);
await writeDB(db);
return json(201, user);
}
// GET /api/users/:id:
const match = url.pathname.match(/^\/api\/users\/(\d+)$/);
if (req.method === "GET" && match) {
const db = await readDB();
const user = db.users.find(u => u.id === Number(match[1]));
return user ? json(200, user) : json(404, { error: "یافت نشد" });
}
json(404, { error: "مسیر یافت نشد" });
} catch (e) {
json(500, { error: e.message });
}
});
server.listen(process.env.PORT || 3000);
مدیریت Packageها در Node
// ساخت پروژه:
// npm init -y
// node_modules — کد نصبشده:
// ├── lodash/
// ├── express/
// └── ...
// package.json — تنظیمات:
// dependencies — تولیدی
// devDependencies — توسعه
// اجرای محلی پکیجها:
// npx eslint .
// اسکریپت main:
{
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
}
}
برنامه خط فرمان (CLI)
#!/usr/bin/env node
// فایل cli.js
const args = process.argv.slice(2);
const command = args[0];
switch (command) {
case "init":
console.log("راهاندازی پروژه...");
break;
case "build":
console.log("ساخت...");
break;
default:
console.log(`
استفاده: cli.js <command>
دستورات:
init راهاندازی
build ساخت
`);
}
// package.json:
{
"bin": {
"mycli": "./cli.js"
}
}
// npm link → mycli build
جمعبندی
| ماژول | کاربرد |
|---|---|
fs | فایل و پوشه |
path | مسیرهای امن |
http | سرور و کلاینت |
events | EventEmitter |
stream | داده جاری |
process | محیط و کنترل |
این مبحث بخشی از دوره آموزش کامل جاوا اسکریپت است.