Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,它使得开发者可以使用 JavaScript 编写服务器端代码。Node.js 采用了事件驱动、非阻塞 I/O 模型,这使得它非常适合处理高并发的网络应用。本教程将带你从零开始学习 Node.js,涵盖基本概念、安装、核心模块、异步编程、以及如何构建一个简单的 Web 服务器。
Node.js 由 Ryan Dahl 于 2009 年创建,它的出现使得 JavaScript 不再局限于浏览器环境,而是可以在服务器端运行。Node.js 的核心优势在于其非阻塞 I/O 模型,这使得它能够高效地处理大量并发请求。
Node.js 采用事件驱动和非阻塞 I/O 模型。事件驱动意味着 Node.js 使用事件循环来处理请求,而不是为每个请求创建一个新的线程。非阻塞 I/O 意味着当 Node.js 执行 I/O 操作(如读取文件或查询数据库)时,它不会等待操作完成,而是继续执行其他任务。当 I/O 操作完成后,Node.js 会触发一个事件,并调用相应的回调函数。
虽然 Node.js 是单线程的,但它通过事件循环和异步 I/O 操作来实现并发。Node.js 内部使用线程池来处理某些操作(如文件 I/O 和 DNS 查询),但开发者编写的代码运行在单线程中。这种设计使得 Node.js 能够高效地处理大量并发请求,而不需要为每个请求创建新的线程。
在开始编写 Node.js 代码之前,你需要先安装 Node.js。Node.js 可以在 Windows、macOS 和 Linux 上运行。
你可以从 Node.js 官方网站 下载适合你操作系统的安装包。Node.js 提供了两个版本:LTS(长期支持版)和 Current(*版)。对于生产环境,建议使用 LTS 版本。
安装完成后,你可以通过以下命令验证 Node.js 是否安装成功:
node -v
如果安装成功,该命令会输出 Node.js 的版本号。
Node.js 自带一个包管理工具 npm(Node Package Manager),它可以帮助你安装和管理第三方库。你可以通过以下命令验证 npm 是否安装成功:
npm -v
Node.js 提供了一些内置的核心模块,这些模块可以帮助你完成常见的任务,如文件操作、网络请求、事件处理等。
fs
模块fs
模块用于文件系统操作。你可以使用它来读取、写入、删除文件等。
const fs = require('fs');
// 读取文件
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// 写入文件
fs.writeFile('example.txt', 'Hello, Node.js!', (err) => {
if (err) throw err;
console.log('File written successfully');
});
http
模块http
模块用于创建 HTTP 服务器和客户端。你可以使用它来构建 Web 服务器。
const http = require('http');
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, World!\n');
});
server.listen(3000, '127.0.0.1', () => {
console.log('Server running at http://127.0.0.1:3000/');
});
events
模块events
模块用于处理事件。你可以使用它来创建自定义事件并监听这些事件。
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('An event occurred!');
});
myEmitter.emit('event');
Node.js 的核心是异步编程。由于 Node.js 是非阻塞的,因此在处理 I/O 操作时,通常使用回调函数、Promise 或 async/await 来处理异步任务。
回调函数是处理异步操作的最基本方式。当异步操作完成时,回调函数会被调用。
const fs = require('fs');
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
Promise 是一种更现代的异步处理方式,它可以帮助你避免“回调地狱”。
const fs = require('fs').promises;
fs.readFile('example.txt', 'utf8')
.then(data => {
console.log(data);
})
.catch(err => {
console.error(err);
});
async/await
是 ES2017 引入的语法糖,它使得异步代码看起来像同步代码。
const fs = require('fs').promises;
async function readFile() {
try {
const data = await fs.readFile('example.txt', 'utf8');
console.log(data);
} catch (err) {
console.error(err);
}
}
readFile();
现在你已经掌握了 Node.js 的基本概念和核心模块,接下来我们将构建一个简单的 Web 服务器。
首先,使用 http
模块创建一个简单的 Web 服务器。
const http = require('http');
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, World!\n');
});
server.listen(3000, '127.0.0.1', () => {
console.log('Server running at http://127.0.0.1:3000/');
});
你可以通过检查 req.url
来处理不同的路由。
const http = require('http');
const server = http.createServer((req, res) => {
if (req.url === '/') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, World!\n');
} else if (req.url === '/about') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('About page\n');
} else {
res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end('Page not found\n');
}
});
server.listen(3000, '127.0.0.1', () => {
console.log('Server running at http://127.0.0.1:3000/');
});
虽然 Node.js 的内置模块可以处理基本的 Web 服务器功能,但在实际开发中,通常会使用第三方框架如 Express.js 来简化开发。
首先,安装 Express.js:
npm install express
然后,使用 Express.js 创建一个 Web 服务器:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello, World!');
});
app.get('/about', (req, res) => {
res.send('About page');
});
app.listen(3000, () => {
console.log('Server running at http://127.0.0.1:3000/');
});
Node.js 是一个强大的 JavaScript 运行时环境,它使得开发者可以使用 JavaScript 编写服务器端代码。通过事件驱动和非阻塞 I/O 模型,Node.js 能够高效地处理高并发请求。本教程介绍了 Node.js 的基本概念、安装方法、核心模块、异步编程以及如何构建一个简单的 Web 服务器。希望这些内容能够帮助你入门 Node.js,并为你进一步学习打下坚实的基础。