likes
comments
collection
share

Node.js开发实战

作者站长头像
站长
· 阅读数 5

Node.js知识点

Node.js内置模块包括了一系列为常见任务提供封装的模块,如文件系统操作、HTTP 服务器与客户端、加密等。这些模块可以通过require函数直接引入到你的Node.js程序中,无需安装额外的包。一些常用的内置模块包括:

fs:用于文件系统相关操作,如读写文件。

httphttps:用于创建HTTP服务器或客户端。

path:提供了一些实用工具函数,用于处理文件与目录的路径。

crypto:提供加密功能,包括对称加密、哈希算法等。

events:允许创建、触发、监听自定义事件。

非阻塞I/O

非阻塞I/O是指I/O操作(如文件读写、网络请求等)不会导致程序暂停等待操作完成。相反,程序可以继续执行其他任务,并在I/O操作完成时收到通知。这与传统的同步(阻塞)I/O形成对比,后者在操作完成之前会挂起执行线程。

异步编程之Callback

Callback(回调函数)是异步编程的基本概念,指的是被异步操作完成时调用的函数。它是实现非阻塞I/O的一种方式。Node.js广泛使用回调来处理异步操作。例如,读取文件时,你会提供一个函数作为fs.readFile的参数,该函数会在读取操作完成后被调用。

const fs = require('fs');
fs.readFile('/path/to/file''utf8'(err, data) => {
  if (err) throw err;
  console.log(data);
});

事件循环

Node.js的事件循环是其异步行为的核心。它允许Node.js执行非阻塞I/O操作——尽管JavaScript是单线程的——通过将事件(如文件读取完成)的处理和执行放入事件队列中,并在主程序执行完毕后再按顺序处理这些事件。

异步编程之Promise

Promise是异步编程的一种更先进的模式,比传统的回调函数方法提供了更好的错误处理和链式调用。它表示一个可能现在还不知道结果的操作,但将来会知道结果的对象。


const promise = new Promise((resolve, reject) => {
  fs.readFile('/path/to/file''utf8'(err, data) => {
    if (err) reject(err);
    else resolve(data);
  });
});

promise.then(data => {
  console.log(data);
}).catch(err => {
  console.error(err);
});

异步编程之async/await

async/await是建立在Promise之上的语法糖,使异步代码看起来和同步代码类似,更容易阅读和维护。async关键字可以用来声明一个函数是异步的,而await关键字用于等待一个Promise完成并获取其结果。

async function readFile() {
  try {
    const data = await fs.promises.readFile('/path/to/file''utf8');
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}

readFile();

通过这些概念和代码示例,你可以看到Node.js如何通过事件循环和异步编程模型(如Callback、Promise、async/await)有效地处理非阻塞I/O操作,使得能够构建高性能且高效的应用。

HTTP服务器

HTTP服务器是一种软件服务器,用于处理客户端(如Web浏览器)通过HTTP协议发送的请求,并回应相应的内容,这些内容可能是HTML页面、图片、文件或其他类型的数据。HTTP服务器监听特定的端口(如80或443),等待并处理来自客户端的请求。

Node.js通过内置的http模块提供了创建HTTP服务器的能力,这使得构建基本的HTTP服务器非常简单。

步骤1: 引入HTTP模块

首先,你需要引入Node.js的http模块。

步骤2: 创建HTTP服务器

使用http.createServer()方法创建一个HTTP服务器,该方法接收一个回调函数作为参数,该回调函数会处理即将到来的HTTP请求。此回调函数有两个参数:req(请求对象)和res(响应对象)。

步骤3: 监听端口

最后,使用服务器对象的listen方法监听一个端口,等待客户端的连接。

const http = require('http');
// 创建HTTP服务器
const server = http.createServer((req, res) => {
  // 设置响应头
  res.writeHead(200, {'Content-Type''text/plain'});
  // 发送响应数据 "Hello World"
  res.end('Hello World\n');
});

// 监听3000端口
server.listen(3000() => {
  console.log('Server running at http://127.0.0.1:3000/');
});

在这个例子中,服务器被配置为监听本地的3000端口。对于所有到达的HTTP请求,无论URL是什么,服务器都会响应状态码200(表示成功),并返回纯文本内容"Hello World"。

要运行这个服务器,你需要将这段代码保存到一个.js文件中,比如server.js,然后在命令行中使用Node.js运行这个文件:

node server.js

运行后,打开Web浏览器访问http://127.0.0.1:3000/,你应该会看到显示了“Hello World”。

这是创建HTTP服务器的最基本方法,但Node.js的http模块提供了丰富的API来处理更复杂的情况,如处理不同的HTTP方法(GET、POST等)、路由、设置cookies、处理文件上传等。

Node.js的http模块确实提供了一系列功能丰富的API,允许开发者处理更复杂的HTTP服务器场景。这些功能可以帮助你实现更高级的功能,比如路由控制、处理不同的HTTP请求方法、设置HTTP头、管理cookies以及文件上传等。让我们通过一些示例来探讨如何使用这些API。

处理不同的HTTP请求方法

HTTP协议定义了多种请求方法,如GET、POST、PUT等。你可以通过检查req.method来响应不同类型的请求。

const http = require('http');
const server = http.createServer((req, res) => {
  if (req.method === 'GET') {
    res.end('Received a GET request');
  } else if (req.method === 'POST') {
    res.end('Received a POST request');
  } else {
    res.statusCode = 405// Method Not Allowed
    res.end();
  }
});

server.listen(3000);

路由控制

在更复杂的应用中,你可能需要根据请求的URL来提供不同的响应。这可以通过简单的条件语句实现,尽管对于复杂应用,使用专门的路由库(如express)会更方便。

const http = require('http');
const server = http.createServer((req, res) => {
  if (req.url === '/') {
    res.end('Home Page');
  } else if (req.url === '/about') {
    res.end('About Page');
  } else {
    res.statusCode = 404// Not Found
    res.end('Page Not Found');
  }
});

server.listen(3000);

设置HTTP头和管理Cookies

HTTP头部用于提供关于HTTP请求或响应的信息。例如,你可以设置内容类型或处理cookies。

const http = require('http');
const server = http.createServer((req, res) => {
  // 设置内容类型
  res.setHeader('Content-Type''text/html');
  // 设置cookie
  res.setHeader('Set-Cookie', ['type=ninja''language=javascript']);
  res.end('<p>This is an HTML paragraph</p>');
});

server.listen(3000);

处理文件上传

处理文件上传稍微复杂一些,通常需要处理multipart/form-data类型的POST请求。Node.js核心模块支持这一点,但处理起来相对繁琐。许多人会转而使用如multerformidable等第三方库来简化文件上传。

以下是一个使用Node.js原生方式接收文本数据的简化示例。对于文件,流程类似,但需要更多的代码来处理文件流和文件存储。

const http = require('http');
const { StringDecoder } = require('string_decoder');
const server = http.createServer((req, res) => {
  if (req.method === 'POST') {
    const decoder = new StringDecoder('utf-8');
    let body = '';
    req.on('data'(chunk) => {
      body += decoder.write(chunk);
    });
    req.on('end'() => {
      body += decoder.end();
      console.log(body); // 打印POST请求体
      res.end('POST data received');
    });
  } else {
    res.statusCode = 404;
    res.end();
  }
});
server.listen(3000);

在 Node.js 中,反向代理和缓存服务是两种常用的技术,用于提高网站和应用的性能和可伸缩性。这里将分别解释它们是什么,并提供代码示例来说明如何在 Node.js 项目中实现它们。

反向代理(Reverse Proxy)

反向代理位于客户端和服务器之间,接收客户端的请求然后转发给内部服务器。它可以作为负载均衡器来分发流量、增加安全性(通过隐藏服务器真实IP)、缓存内容以及压缩数据等。Node.js 可以利用 http-proxy 库来创建反向代理服务器。

代码示例:

安装 http-proxy 模块:

npm install http-proxy --save

创建一个简单的反向代理服务器:

const http = require('http');
const httpProxy = require('http-proxy');

// 创建一个代理服务器
const proxy = httpProxy.createProxyServer({});

// 创建你的目标服务器
http.createServer(function(req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('响应来自目标服务器');
  res.end();
}).listen(9000);

// 创建反向代理服务器
http.createServer(function(req, res) {
  // 在这里可以执行任何预处理,然后转发请求
  proxy.web(req, res, { target: 'http://localhost:9000' });
}).listen(8000);

console.log("反向代理运行在 http://localhost:8000");

缓存服务(Caching)

缓存是存储请求内容的副本,以便于快速访问。在 Node.js 中,缓存可以通过多种方式实现,包括内存存储、文件系统或专用缓存服务器(如 Redis)。缓存可以显著减少数据库的查询次数,提高响应速度。

内存缓存示例:

安装 node-cache 模块:

npm install node-cache --save

使用 node-cache 创建一个简单的缓存例子:

const NodeCache = require("node-cache");
const myCache = new NodeCache();

const key = "uniqueKey";
const value = "存储的数据";

// 存储数据到缓存中,设置存活时间为10分钟(600秒)
myCache.set(key, value, 600);

// 从缓存中获取数据
const cachedData = myCache.get(key);

if (cachedData) {
  console.log("从缓存中获取到的数据:", cachedData);
} else {
  console.log("缓存中没有找到数据");
}

结合反向代理和缓存

在实际应用中,反向代理和缓存经常一起使用。反向代理可以负责接收客户端请求、查询缓存;如果缓存中有响应数据,则直接返回给客户端,如果没有,则查询后端服务,同时将响应结果缓存起来,以便于下次快速响应。