nodejs 构建高性能服务器的关键技术

news2024/11/26 0:49:02

nodejs 构建高性能服务器的关键技术

  1. 演示地址 演示地址
  2. 源码地址 源码地址
  3. 获取更多 获取更多
  • 在现代 Web 开发中,Node.js 已成为构建高性能、可扩展网络应用的首选平台之一。它的非阻塞 I/O 模型与事件驱动架构使其能够在处理大量并发请求时表现出色,尤其适合构建实时应用,如聊天系统、数据流处理等。这篇博客将介绍 Node.js 的核心特性、常用模块以及如何利用其优势来开发高效的服务器端应用。

什么是 Node.js?

  • Node.js 是一个基于 Chrome V8 JavaScript 引擎 的 JavaScript 运行时。它允许开发者使用 JavaScript 编写服务器端代码,而不仅仅是前端代码。与传统的多线程 Web 服务器(如 Apache、Tomcat)不同,Node.js 采用 单线程、事件驱动 的架构,这使它能够有效处理高并发请求。

Node.js 的核心特点

  1. 事件驱动、非阻塞 I/O
    Node.js 最大的特点是 非阻塞 I/O,也就是在进行 I/O 操作时(如读取文件、数据库查询或 HTTP 请求),它不会阻塞主线程,而是通过 事件循环 和 回调函数 来处理。这使得即使在 I/O 密集型场景下,Node.js 也能保持高效的响应。
const fs = require('fs');

fs.readFile('example.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});

console.log('This will print first!');
  1. 单线程,但高并发
  • 虽然 Node.js 是单线程的,但它通过 libuv 库将一些复杂的操作交给底层线程池处理,如文件读写、网络请求等。这种模型使 Node.js 在处理大量并发请求时拥有极高的性能,避免了传统多线程 Web 服务器因上下文切换而导致的性能损耗。

nodejs 架构图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • Node.js 架构的核心是 事件驱动、非阻塞 I/O,它利用了 事件循环(Event Loop) 来处理 I/O 操作,实现高效的并发处理。主要组件包括:
  1. V8 引擎:这是 Google 的 JavaScript 引擎,负责解析和执行 JavaScript 代码。
  2. libuv:Node.js 使用的库,支持事件驱动、异步 I/O 操作,主要处理文件系统、网络、DNS、以及定时器等。
  3. 事件循环(Event Loop):Node.js 的心脏,管理和调度 I/O 事件,使其可以通过单线程处理多任务。
  4. 回调队列(Callback Queue):事件循环将完成的异步任务的回调函数放入回调队列中,逐一执行。
  5. 线程池:尽管 Node.js 是单线程的,但底层通过 libuv 维护一个线程池,用来处理 CPU 密集型任务。

常见全局变量

  1. __dirname
  • 表示当前执行的脚本所在目录的绝对路径。
console.log(__dirname);
  1. __filename
  • 表示当前执行的脚本文件的绝对路径。
console.log(__filename);
  1. global
  • global 是 Node.js 的全局对象,类似于浏览器中的 window 对象。
  • 任何挂载到 global 的属性或方法都可以在整个应用中访问。
global.myVar = 'Hello, World!';
console.log(global.myVar); // 输出: Hello, World!
  1. process
  • process 对象提供有关当前 Node.js 进程的信息以及控制进程的方法。它包含关于环境、命令行参数、标准输入输出流等信息。
console.log(process.version); // Node.js 的版本
console.log(process.env); // 环境变量
console.log(process.argv); // 命令行参数
  1. Buffer
  • Buffer 对象用于处理二进制数据流,特别是在处理文件或网络数据时非常有用。
const buf = Buffer.from('Hello, World!');
console.log(buf.toString()); // 输出: Hello, World!
  1. setTimeout()
  • 用于延迟执行代码。与浏览器中的 setTimeout 一样,但在 Node.js 中,这是全局函数,不需要引入任何模块。
setTimeout(() => {
  console.log('Executed after 1 second');
}, 1000);
  1. setInterval
  • 用于定时执行代码。与 setTimeout() 类似,但它会以固定的时间间隔重复执行。
setInterval(() => {
  console.log('Repeated every 2 seconds');
}, 2000);
  1. clearTimeout
  • 用于取消由 setTimeout() 创建的定时器。
const timer = setTimeout(() => {
  console.log('This will not be logged');
}, 5000);

clearTimeout(timer);
  1. clearInterval
  • 用于取消由 setInterval() 创建的定时器。
const interval = setInterval(() => {
  console.log('This will not repeat');
}, 2000);

clearInterval(interval);
  1. require()
  • require() 函数用于引入模块。它是 CommonJS 模块系统的一部分。
const fs = require('fs');
  1. module
  • module 对象表示当前模块本身。它包含关于模块的信息,比如 module.exports 属性,它用于导出模块的内容。
console.log(module.exports); // 打印导出的内容
  1. exports
  • exports 是 module.exports 的快捷方式,用于导出模块的属性或方法。
exports.myFunction = function () {
  return 'Hello!';
};
  1. console
  • 提供与控制台输出相关的方法,如 console.log()、console.error()、console.warn() 等。
console.log('This is a log message');
console.error('This is an error message');

path 常用方法

  • path 模块是 Node.js 的核心模块之一,提供了处理和转换文件路径的实用方法。它能够帮助开发者跨平台地处理文件路径问题,因为不同操作系统的路径分隔符不同(Windows 使用 \,而 POSIX 系统(如 Linux 和 macOS)使用 /)。
  1. path.basename(p[, ext])
  • 作用:返回路径的最后一部分,也就是文件名。如果提供了 ext 参数,会从结果中移除这个扩展名。
  • 参数:
  1. p: 文件路径。
  2. ext: 可选,文件扩展名(若提供此参数,会从返回值中移除它)。
const path = require('path');
const filePath = '/user/local/bin/file.txt';
console.log(path.basename(filePath)); // 输出: file.txt
console.log(path.basename(filePath, '.txt')); // 输出: file
  1. path.dirname§
  • 作用:返回路径的目录部分。

  • 参数:

  • p: 文件路径。

const path = require('path');
const filePath = '/user/local/bin/file.txt';
console.log(path.dirname(filePath)); // 输出: /user/local/bin
  1. path.extname§
  • 作用:返回路径中文件的扩展名。
  • 参数:
  • p: 文件路径。
const path = require('path');
const filePath = '/user/local/bin/file.txt';
console.log(path.extname(filePath)); // 输出: .txt
  1. path.join([…paths])
  • 作用:使用平台特定的分隔符将所有给定的路径片段连接在一起,并规范化生成的路径。
const path = require('path');
const joinedPath = path.join('/user', 'local', 'bin/file.txt');
console.log(joinedPath); // 输出: /user/local/bin/file.txt
  1. path.resolve([…paths])
  • 作用:将路径或路径片段解析为绝对路径。如果没有给定路径片段,则使用当前工作目录。
const path = require('path');

const absolutePath = path.resolve('file.txt');
console.log(absolutePath);

const resolvedPath = path.resolve('/user', 'local', 'bin/file.txt');
console.log(resolvedPath);
  1. path.normalize§
  • 作用:规范化给定的路径,解析 … 和 . 片段,并移除多余的斜杠。
  • 参数:
  • p: 需要规范化的路径。
const path = require('path');
const normalizedPath = path.normalize('/user//local/../bin/file.txt');
console.log(normalizedPath);
  1. path.isAbsolute§
  • 作用:判断给定路径是否为绝对路径。
  • 参数:
  • p: 文件路径。
  • 返回:布尔值,表示路径是否是绝对路径。
const path = require('path');
console.log(path.isAbsolute('/user/local/bin')); // 输出: true
console.log(path.isAbsolute('file.txt')); // 输出: false
  1. path.relative(from, to)
  • 作用:根据两个给定的路径,返回相对路径。
  • 参数:
  • from: 起始路径。
  • to: 目标路径。
const path = require('path');
const fromPath = '/user/local/bin';
const toPath = '/user/local/lib/file.txt';
console.log(path.relative(fromPath, toPath)); // 输出: ../lib/file.txt
  1. path.parse§
  • 作用:将路径解析为一个对象,包含 root、dir、base、ext 和 name 属性。
  • 参数:
  • p: 文件路径。
  • 返回:一个对象,包含路径的各个部分。
const path = require('path');
const filePath = '/user/local/bin/file.txt';
const parsedPath = path.parse(filePath);
console.log(parsedPath);
//-------------------------------------
{
  root: '/',
  dir: '/user/local/bin',
  base: 'file.txt',
  ext: '.txt',
  name: 'file'
}
  1. path.format(pathObject)
  • 作用:将 path.parse() 返回的对象重新组合为路径。
  • 参数:
  • pathObject: 包含路径信息的对象,类似 path.parse() 的输出。
const path = require('path');
const pathObject = {
  root: '/',
  dir: '/user/local/bin',
  base: 'file.txt',
  ext: '.txt',
  name: 'file',
};
const formattedPath = path.format(pathObject);
console.log(formattedPath); // 输出: /user/local/bin/file.txt

Buffer 模块

  • 在 Node.js 中,Buffer 是处理二进制数据的核心模块。它在网络通信、文件读写等场景中非常常用,特别是在处理像 TCP 数据流、文件 I/O 以及其他没有明确编码的原始数据时。
  • 与浏览器 JavaScript 不同,Node.js 中的 Buffer 类可以直接处理和存储二进制数据,且在引入了 TypedArray 之前,这是 Node.js 中唯一可用的处理原始字节的方式。
  1. Buffer.alloc(size[, fill[, encoding]])
  • 作用:分配一个大小为 size 的缓冲区,并用 fill 填充该缓冲区。encoding 是填充时的编码,默认为 ‘utf8’。
const buf = Buffer.alloc(10);
const bufFilled = Buffer.alloc(10, 'a');
console.log(bufFilled.toString());
  1. Buffer.from(array)
  • 作用:将数组、字符串或其他对象转换为 Buffer。
const bufFromArray = Buffer.from([1, 2, 3]);
console.log(bufFromArray); // 输出: <Buffer 01 02 03>

const bufFromString = Buffer.from('Hello, World!', 'utf8');
console.log(bufFromString); // 输出: <Buffer
  • 作用:将 Buffer 中的数据解码为字符串。默认使用 utf8 编码,可以指定起始和结束位置。
const buf = Buffer.from('Hello, World!', 'utf8');
console.log(buf.toString()); // 输出: Hello, World!
console.log(buf.toString('utf8', 0, 5)); // 输出: Hello
  1. buf.write(string[, offset[, length]][, encoding])
  • 作用:将 string 写入 Buffer。offset 是从 Buffer 的哪个位置开始写入,length 是写入的字节数,encoding 是编码格式,默认是 ‘utf8’。
const buf = Buffer.alloc(10);
buf.write('Hello', 0, 'utf8');
console.log(buf.toString()); // 输出: Hello
  1. Buffer.concat(list[, totalLength])
  • 作用:合并多个 Buffer 为一个 Buffer。list 是要合并的 Buffer 数组,totalLength 是合并后 Buffer 的总长度。
const buf1 = Buffer.from('Hello,');
const buf2 = Buffer.from('World!');

const combinedBuf = Buffer.concat([buf1, buf2]);
console.log(combinedBuf.toString());
  1. Buffer.byteLength(string[, encoding])
  • 作用:返回给定字符串的字节长度。
const str = 'hello world';
console.log(Buffer.byteLength(str));
  1. buf.slice([start[, end]])
  • 作用:返回 Buffer 的一个片段,类似于数组的 slice() 方法。
const buf = Buffer.from('Hello, World!', 'utf8');
const sliceBuf = buf.slice(0, 5);
console.log(sliceBuf.toString()); // 输出: Hello
  1. buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])
  • 作用:将当前 Buffer 的内容复制到目标 Buffer。
const buf1 = Buffer.from('Hello');
const buf2 = Buffer.alloc(5);
buf1.copy(buf2);
console.log(buf2.toString()); // 输出: Hello
  1. buf.equals(otherBuffer)
  • 作用:比较两个 Buffer 的内容是否相同。
const buf1 = Buffer.from('ABC');
const buf2 = Buffer.from('ABC');
const buf3 = Buffer.from('DEF');

console.log(buf1.equals(buf2)); // 输出: true
console.log(buf1.equals(buf3)); // 输出: false
  1. buf.indexOf(value[, byteOffset][, encoding])
  • 作用:查找 Buffer 中的某个值,返回其首次出现的位置,如果没有找到则返回 -1。
const buf = Buffer.from('Hello, World!', 'utf8');
console.log(buf.indexOf('World')); // 输出: 7
console.log(buf.indexOf('XYZ')); // 输出: -1
  1. buf.fill(value[, offset[, end]][, encoding])
  • 作用:用指定值填充 Buffer 的内容。
const buf = Buffer.alloc(10);
buf.fill('a');
console.log(buf.toString()); // 输出: aaaaaaaaaa

fs 常用方法

  • fs 模块是 Node.js 提供的核心模块之一,用于处理文件系统相关操作。它提供了同步和异步方法,支持文件的读写、文件夹操作、文件权限修改等功能
  1. fs.readFile(path, [options], callback)
  • 作用:异步读取文件的全部内容。
  • 参数:
  1. path: 文件路径。
  2. options: 可选,指定编码或返回格式(默认为 Buffer)。
  3. callback: 回调函数,传递 (err, data)
const fs = require('fs');

fs.readFile('data.txt', 'utf-8', (err, data) => {
  if (err) throw err;
  console.log(data);
});
  1. fs.readFileSync(path, [options])
  • 作用:同步读取文件的全部内容。返回读取到的数据。
  • 参数:
  • path: 文件路径。
  • options: 可选,指定编码或返回格式。
const fs = require('fs');
const data = fs.readFileSync('data.txt', 'utf-8');
console.log('data', data);
  1. fs.writeFile(file, data, [options], callback)
  • 作用:异步写入数据到文件,如果文件不存在会创建文件。
  • 参数:
  1. file: 文件路径。
  2. data: 要写入的数据。
  3. options: 可选,指定编码。
  4. callback: 回调函数,传递 (err)。
const fs = require('fs');
fs.writeFile('data.txt', 'change info', (err) => {
  if (err) throw err;
  console.log('file hash been write');
});
  1. fs.writeFileSync(file, data, [options])
  • 作用:同步写入数据到文件。
const fs = require('fs');
fs.writeFileSync('data.txt', 'change info', 'utf-8');
console.log('file has been written');
  1. fs.appendFile(file, data, [options], callback)
  • 作用:异步向文件追加数据。如果文件不存在则创建文件。
const fs = require('fs');
fs.appendFile('data.txt', 'this is appended txt.\n', (err) => {
  if (err) throw err;
  console.log('Data append to file');
});
  1. fs.appendFileSync(file, data, [options])
  • 作用:同步向文件追加数据。
const fs = require('fs');
fs.appendFileSync('data.txt', 'This is appended text.\n');
console.log('Data appended to file.');
  1. fs.rename(oldPath, newPath, callback)
  • 作用:异步重命名文件或文件夹。
  • 参数:
  • oldPath: 旧路径。
  • newPath: 新路径。
  • callback: 回调函数,传递 (err)。
const fs = require('fs');

fs.rename('file.txt', 'file1.txt', (err) => {
  if (err) throw err;
  console.log('Rename complete.');
});
  1. fs.renameSync(oldPath, newPath)
  • 作用:同步重命名文件或文件夹。
const fs = require('fs');

fs.renameSync('file1.txt', 'file.txt');
console.log('Rename complete.');
  1. fs.unlink(path, callback)
  • 作用:异步删除文件。
  • 参数:
  1. path: 文件路径。
  2. callback: 回调函数,传递 (err)。
const fs = require('fs');
fs.unlink('file.txt', (err) => {
  if (err) throw err;
  console.log('file delete');
});
  1. fs.unlinkSync(path)
  • 作用:同步删除文件
const fs = require('fs');
fs.unlinkSync('file.txt');
console.log('file delete');
  1. fs.readdir(path, [options], callback)
  • 作用:异步读取指定目录的内容,返回文件和子目录的数组。
  • 参数:
  1. path: 目录路径。
  2. options: 可选,encoding 或 withFileTypes(是否返回 Dirent 对象)。
  3. callback: 回调函数,传递 (err, files)。
const fs = require('fs');

fs.readdir('./', (err, files) => {
  if (err) throw err;
  console.log(files); // 输出文件和目录的列表
});
  1. fs.readdirSync(path, [options])
  • 作用:同步读取目录内容。
const fs = require('fs');
const files = fs.readdirSync('./');
console.log(files);
  1. fs.mkdir(path[, options], callback)
  • 作用:异步创建目录。
  • 参数:
  1. path: 要创建的目录路径。
  2. options: 可选,是否递归创建,或设置权限模式。
  3. callback: 回调函数,传递 (err)。
const fs = require('fs');

fs.mkdir('test', (err) => {
  if (err) throw err;
  console.log('Directory created.');
});
  1. fs.mkdirSync(path[, options])
  • 作用:同步创建目录。
const fs = require('fs');
fs.mkdirSync('test');
console.log('Directory created.');
  1. fs.rmdir(path[, options], callback)
  • 作用:异步删除目录。该目录必须为空。
  • 参数:
  1. path: 目录路径。
  2. options: 可选,recursive: true 表示递归删除非空目录(实验性功能)。
  3. callback: 回调函数,传递 (err)。
const fs = require('fs');
fs.rmdir('test', (err) => {
  if (err) throw err;
  console.log('directory deleted.');
});
  1. fs.rmdirSync(path[, options])
  • 作用:同步删除目录。
const fs = require('fs');
fs.rmdirSync('new_directory');
console.log('Directory deleted.');
  1. fs.stat(path, callback)
  • 作用:异步获取文件或目录的状态信息,返回 fs.Stats 对象。
  • 参数:
  1. path: 文件或目录路径。
  2. callback: 回调函数,传递 (err, stats)。
const fs = require('fs');
fs.stat('file.txt', (err, stats) => {
  if (err) throw err;
  console.log(stats);
});
  1. fs.statSync(path)
  • 作用:同步获取文件或目录的状态信息。
const fs = require('fs');
const stats = fs.statSync('example.txt');
console.log(stats);
  1. fs.existsSync(path)
  • 作用:同步检查文件或目录是否存在(注意:该方法已废弃,推荐使用 fs.access())。
const fs = require('fs');

if (fs.existsSync('file.txt')) {
  console.log('File exists.');
}
  1. fs.access(path[, mode], callback)
  • 作用:检查文件或目录的权限。mode 可以用来检查读、写或执行权限。
  • 参数:
  1. path: 文件路径。
  2. mode: 可选,文件权限检查。
  3. callback: 回调函数,传递 (err)。
const fs = require('fs');

fs.access('example.txt', fs.constants.R_OK | fs.constants.W_OK, (err) => {
  console.log(err ? 'No access!' : 'File can be read and written.');
});

vm 模块

  • Node.js 提供了许多强大的内置模块,其中的 vm 模块(Virtual Machine,虚拟机)特别值得关注。它允许我们在独立的上下文中执行 JavaScript 代码,这在某些场景中非常有用,比如执行不信任的代码、沙箱化运行环境等。
  1. 什么是 vm 模块
  • vm 模块允许在 Node.js 中创建沙箱化的虚拟机上下文,运行的 JavaScript 代码可以隔离在单独的上下文中,避免对主应用环境产生副作用。使用 vm 模块,可以执行动态代码,而无需担心代码直接影响主线程或全局环境。
  1. vm.runInThisContext()
  • vm.runInThisContext() 方法类似于 eval(),但执行的代码是在与当前上下文分离的环境中执行的,且无法访问主上下文的变量。
const vm = require('vm');
const code = `var x=10;x += 5`;
const result = vm.runInThisContext(code);
console.log('result', result);
  1. vm.runInNewContext()
  • vm.runInNewContext() 可以在全新的上下文中执行代码,可以指定上下文的对象,用作代码执行时的全局对象。
const vm = require('vm');

const context = { x: 1 };
vm.runInNewContext('x += 40;', context);
console.log(context.x); // 输出 41
  • 在这里,代码是在新的上下文中执行的,并且 context 对象被当作全局对象传入执行环境中。
  1. vm.createContext()
  • vm.createContext() 用于创建一个新的上下文对象。在这个上下文中,可以安全地执行代码。
const vm = require('vm');

const sandbox = { animal: 'cat', count: 2 };
const context = vm.createContext(sandbox);
vm.runInContext('count += 1; name = "Tom";', context);

console.log(sandbox);
  • 此方法适用于在创建的上下文中运行复杂的代码,同时可以对上下文对象进行控制。
  1. vm.Script()
  • vm.Script() 可以将代码编译为一个可执行的脚本对象,并且可以多次执行该脚本。
const vm = require('vm');

const script = new vm.Script(`count += 1;name="tom"`);
const sandbox = { count: 0 };
const context = vm.createContext(sandbox);

script.runInContext(context);
console.log(sandbox);

// 输出 { count: 2, name: 'Jerry' }
  • vm.Script() 的优势在于,可以多次执行同一个编译后的代码,避免重复编译带来的性能开销

事件模块 (events) 详解

  • 在 Node.js 中,事件驱动架构是其核心之一。events 模块是用于管理和触发事件的内置模块,提供了一种实现 观察者模式 的机制。通过事件模块,开发者可以定义事件、绑定事件处理函数,并在合适的时候触发这些事件。
  1. 事件驱动模型简介
  • Node.js 的核心架构基于事件驱动模型。与传统的多线程模型不同,Node.js 使用 单线程、异步 I/O 和 事件循环 来处理并发。所有的 I/O 操作(如网络请求、文件读写等)都是异步的,完成后会通过事件通知回调函数,从而使代码可以继续执行其他任务,而不会被阻塞。
  1. 监听事件
  • 可以使用 on() 方法为事件绑定监听器。监听器函数会在事件触发时执行。
const EventEmitter = require('events');
const emitter = new EventEmitter();

emitter.on('greet', () => {
  console.log('Hello world');
});

emitter.emit('greet');
  • 在这个例子中,我们使用 on() 方法监听了 greet 事件,当使用 emit() 方法触发该事件时,绑定的处理函数会执行。
  1. 移除监听器
    可以使用 removeListener() 或 off() 方法移除某个特定事件的监听器。
const EventEmitter = require('events');
const emitter = new EventEmitter();

emitter.on('greet', () => {
  console.log('Hello, World!');
});

const callback = () => console.log('This will not run');
emitter.on('removeEvent', callback);

emitter.removeListener('removeEvent', callback);
emitter.emit('removeEvent'); // 无输出

http 模块详解

  • Node.js 的核心特性之一是其内置的 HTTP 模块。通过 http 模块,开发者可以轻松创建 HTTP 服务器和客户端,从而实现 Web 应用、API 服务或其他网络应用。http 模块是 Node.js 中处理网络请求的基础,它是基于事件驱动的,支持异步处理。
  1. HTTP 模块简介
  • Node.js 内置的 http 模块提供了创建 HTTP 服务器和客户端的功能。与浏览器端的 HTTP 请求不同,Node.js 的 http 模块允许服务器端代码主动监听并处理请求。
  1. 创建 HTTP 服务器
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, () => {
  console.log('Server running at http://127.0.0.1:3000/');
});
  1. http.createServer([requestListener])
  • http.createServer() 方法用于创建 HTTP 服务器。requestListener 是一个回调函数,每当服务器接收到 HTTP 请求时,都会调用该回调函数。回调函数的两个参数是:
    req:代表 HTTP 请求的对象。
    res:代表 HTTP 响应的对象。
  1. 监听请求
  • 通过 server.listen() 方法,服务器可以开始监听指定的端口(如 3000),当有 HTTP 请求到达时,requestListener 会被触发。
  1. 发送响应
  • 在回调函数中,我们可以通过 res.writeHead() 设置响应状态码和响应头,使用 res.end() 结束响应并返回数据。
  1. 处理查询参数
  • 在处理 URL 时,可能需要解析 URL 中的查询参数(如 ?name=John&age=30)。Node.js 内置了 url 模块来帮助解析 URL 和查询参数。
const url = require('url');

const server = http.createServer((req, res) => {
  const parsedUrl = url.parse(req.url, true);
  const query = parsedUrl.query;

  res.statusCode = 200;
  res.setHeader('Content-Type', 'application/json');
  res.end(JSON.stringify(query)); // 返回解析后的查询参数
});

server.listen(3000);
  1. 使用 HTTP 客户端
  • 除了创建 HTTP 服务器,Node.js 的 http 模块还可以用作 HTTP 客户端,发送 HTTP 请求。
const http = require('http');

const options = {
  hostname: 'example.com',
  port: 80,
  path: '/',
  method: 'GET',
};

const req = http.request(options, (res) => {
  let data = '';

  res.on('data', (chunk) => {
    data += chunk;
  });

  res.on('end', () => {
    console.log('Response:', data);
  });
});

req.on('error', (error) => {
  console.error('Error:', error);
});

req.end();
  • 在这个例子中,http.request() 用于发起 HTTP 请求,设置请求选项(如 hostname、port、path 等),并处理服务器返回的响应。
  1. 支持
  • 对于安全通信,Node.js 提供了 https 模块。它的用法与 http 模块类似,但支持 SSL/TLS 加密。需要将 http 替换为 https。
const https = require('https');

https.get('https://example.com', (res) => {
  let data = '';

  res.on('data', (chunk) => {
    data += chunk;
  });

  res.on('end', () => {
    console.log('Response:', data);
  });
});

联系作者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2193228.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

环形缓冲区(Ring Buffer)在STM32 HAL库中的应用:防止按键丢失

环形缓冲区&#xff08;Ring Buffer&#xff09;又称为循环缓冲区或圆形队列&#xff0c;是一种数据结构&#xff0c;它用于管理固定大小的数据存储空间。环形缓冲区本质是一个一维数组&#xff0c;不过是收尾相连的&#xff0c;类比一条蛇咬自己尾巴。 环形缓冲区重要性&…

危机四伏|盘点紧盯我国的五大APT组织

毒云藤&#xff08;APT-C-01&#xff09; 命名&#xff1a;该组织是 360 独立发现的&#xff0c;并率先披露了该组织的部分相关信息符合 360 对 APT 组织就行独立命名的条件。 360 威胁情报中心将 APT-C-01 组织命名为“毒云藤”&#xff0c;主要是考虑了以下几方面的因素&…

L1415 【哈工大_操作系统】CPU调度策略一个实际的schedule函数

L2.7 CPU调度策略 1、调度的策略 周转时间&#xff1a;任务进入到任务结束&#xff08;后台任务更关注&#xff09;响应时间&#xff1a;操作发生到响应时&#xff08;前台任务更关注&#xff09;吞吐量&#xff1a;CPU完成的任务量 响应时间小 -> 切换次数多 -> 系统…

curses函数库简介及使用

curses函数库简介及使用 导语curses简介屏幕输出读取清除移动字符 键盘键盘模式输入 窗口WINDOW常用函数屏幕刷新优化 子窗口keypad彩色显示pad总结参考文献 导语 curses函数库主要用来实现对屏幕和光标的操作&#xff0c;它的功能定位处于简单文本行程序和完全图形化界面之间…

【重学 MySQL】五十八、文本字符串(包括 enum set)类型

【重学 MySQL】五十八、文本字符串&#xff08;包括 enum set&#xff09;类型 CHAR 和 VARCHARTEXT 系列ENUMSET示例注意事项 在 MySQL 中&#xff0c;文本字符串类型用于存储字符数据。这些类型包括 CHAR、VARCHAR、TEXT 系列&#xff08;如 TINYTEXT、TEXT、MEDIUMTEXT 和 L…

鸿蒙开发(NEXT/API 12)【管理应用与Wear Engine服务的连接状态】手机侧应用开发

监测应用与Wear Engine服务的连接状态 华为运动健康App在后台停止服务&#xff08;如功耗过高&#xff09;&#xff0c;从而导致应用与Wear Engine服务的连接状态发生变化。对于类似这种不确定的断开情况&#xff0c;开发者可以通过本功能特性了解当前应用和Wear Engine的连接…

NatGo我的世界联机篇

书接上回 这里的TCP是JAVA&#xff0c;UDP是BE&#xff0c;选自适合你的映射类型 内网端口就填下面图片在你游戏同一个地方的数字!!! 就是我填12345的地方&#xff0c;mod-自定义局域网联机 默认 25565&#xff0c;如果出现无法创建本地游戏&#xff0c;那可能是端口被占用或…

卷积层是如何学习到图像特征的?

你好啊&#xff0c;我是董董灿。 想搞懂这个问题&#xff0c;需要先了解我们所说的特征指的是什么&#xff1f;然后再了解卷积核是如何学到的特征。 我们一步步来。 1、我们先来理解图像的特征 对于一张原始图像而言&#xff0c;说原始图像是相对于经过卷积处理而言的。 对…

【文心智能体】旅游攻略版,手把手教你调用插件实现智能体,绝对的干货满满!

1.灵感来源 需要创建一个智能体&#xff0c;首先当然是需要一个创作灵感啦&#xff0c;那么恰逢国庆假期&#xff0c;但是网上各种各样的旅游资料使我头晕目眩&#xff0c;刚好呢百度的文心智能体平台给我们提供了各种各样的插件以及知识库&#xff0c;可以供我们随心所欲地调…

嵌入式硬件设计中EDA布局与布线实现

大家好,今天主要给大家分享一下,如何使用立创EDA进行布局和布线,具体实现过程如下: 第一:PCB概念介绍 在介绍PCB的时候,先来说明一下,电子管的发明史。 贝尔在1876年发明了电话,爱迪生1879年发明了白炽灯、特斯拉于1888年发明了电动机,所有这些,都为电子学的诞生准…

2024 热门的4大电脑剪辑软件大盘点。

在电脑上进行视频剪辑能够让我们更好的发挥创意&#xff0c;制作出精彩的视频作品。同时也需要依赖一些比较专业的视频剪辑工具。这几款视频剪辑软件&#xff0c;无论是制作个人视频、商业广告还是电影预告片&#xff0c;都是非常不错的选择。 1、福昕电脑剪辑 直达链接&#…

vSAN05:vSAN延伸集群简介与创建、资源要求与计算、高级功能配置、维护、故障处理

目录 vSAN延伸集群延伸集群创建延伸集群的建议网络配置vSAN延伸集群的端口见证主机的资源要求vSAN延伸集群中见证节点带宽占用vSAN延伸集群的允许故障数vSAN延伸集群不同配置下的空间占用 vSAN延伸集群的HA配置vSAN延伸集群的DRS配置vSAN存储策略以及虚拟机/主机策略的互操作vS…

系统架构设计师③:数据块系统

系统架构设计师③&#xff1a;数据块系统 数据库模式 数据库模式是指数据库的结构和组织方式&#xff0c;它描述了数据库中数据的逻辑结构和组织方式&#xff0c;是数据库设计的核心组成部分。以下是关于数据库模式的详细解析&#xff1a; 一、定义与组成 定义&#xff1a;…

4款专业电脑数据恢复软件,帮你保障数据安全。

电脑里面会出现的数据丢失场景有很多&#xff0c;像硬盘故障、回收站清空、电脑格式化、系统崩溃、病毒入侵等等&#xff1b;如果发现数据丢失后&#xff0c;建议应停止使用电脑&#xff0c;避免新的数据写入覆盖丢失的数据。然后再尝试进行数据找回&#xff0c;如果想自己进行…

系统分析师16:系统测试与维护

1 内容概要 2 软件测试类型 2.1 测试类型 动态测试【计算机运行】 白盒测试法&#xff1a;关注内部结构与逻辑灰盒测试法&#xff1a;介于两者之间黑盒测试法&#xff1a;关注输入输出及功能 静态测试【人工监测和计算机辅助分析】 桌前检查代码审查代码走查以上三个都是做的…

【C++11】新特性

前言&#xff1a; C11 是C编程语言的一个重要版本&#xff0c;于2011年发布。它带来了数量可观的变化&#xff0c;包含约 140 个新特性&#xff0c;以及对 C03 标准中约600个缺陷的修正&#xff0c;更像是从 C98/03 中孕育出的新语言 列表初始化 C11 中的列表初始化&#xff0…

社群团购中的用户黏性价值:以开源小程序多商户AI智能名片商城源码为例

摘要&#xff1a;本文探讨社群团购中的用户黏性价值&#xff0c;分析其与传统团购网站的区别&#xff0c;并阐述开源小程序多商户AI智能名片商城源码在增强社群团购用户黏性方面可能发挥的作用。 一、引言 在当今的商业环境中&#xff0c;社群团购逐渐成为一种重要的营销模式。…

新个性化时尚解决方案!Prompt2Fashion:自动生成多风格、类型时尚图像数据集。

今天给大家介绍一种自动化生成时尚图像数据的方法Prompt2Fashion。 首先创建了一组描述&#xff0c;比如“适合婚礼的休闲风格服装”&#xff0c;然后用这些描述来指导计算机生成图像。具体来说&#xff0c;他们使用了大型语言模型来写出这些服装的描述&#xff0c;接着将这些描…

毕业设计 大数据电影数据分析与可视化系统

文章目录 0 简介1 课题背景2 效果实现3 爬虫及实现4 Flask框架5 Ajax技术6 Echarts7 最后 0 简介 今天学长向大家介绍一个机器视觉的毕设项目 &#x1f6a9;基于大数据的电影数据分析与可视化系统 项目运行效果(视频)&#xff1a; 毕业设计 大数据电影评论情感分析 &#x1…