赞
踩
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,用于在服务器端运行 JavaScript。它使用了一个事件驱动、非阻塞式I/O的模型,使得其轻量且高效。Node.js 的包管理器 npm 是全球最大的开源库生态系统。Node.js 能够响应大量的并发请求,适合运用在高并发、I/O密集、少量业务逻辑的场景。
NodeJs 下载路径:https://nodejs.org/en
安装完成后可以在命令行中输入 node -v 和 npm -v 检查是否安装成功?
Node.js 中不能使用 BOM 和 DOM 的 API,可以使用 console 和定时器 API。
Node.js 中的顶级对象是 global,也可以用 globalThis 访问顶级对象。
<ref *1> Object [global] { global: [Circular *1], clearInterval: [Function: clearInterval], clearTimeout: [Function: clearTimeout], setInterval: [Function: setInterval], setTimeout: [Function: setTimeout] { [Symbol(nodejs.util.promisify.custom)]: [Getter] }, queueMicrotask: [Function: queueMicrotask], performance: Performance { nodeTiming: PerformanceNodeTiming { name: 'node', entryType: 'node', startTime: 0, duration: 36.77699999511242, nodeStart: 0.7232999950647354, v8Start: 2.644999995827675, bootstrapComplete: 26.97859999537468, environment: 13.895999997854233, loopStart: -1, loopExit: -1, idleTime: 0 }, timeOrigin: 1698760750401.373 }, clearImmediate: [Function: clearImmediate], setImmediate: [Function: setImmediate] { [Symbol(nodejs.util.promisify.custom)]: [Getter] } }
console.log(globalThis === global) // true
console.dir()
是 JavaScript 中的一个控制台方法,它用于以一种可读的格式显示一个对象的属性和方法。它通常用于调试和了解对象的结构。使用 Node.js 中的 console.dir()
方法来查看对象的方法。例如,查看一个名为 myObject
的对象的方法:
console.dir(myObject, { showHidden: true, depth: null });
这将会在控制台中显示 myObject
对象的所有属性和方法,包括隐藏方法和属性。可以通过设置 depth
参数来控制对象深度的显示。
安装地址:https://nodejs.org/en/download
通过宝塔面板下载上传到 /home
目录
Node 压缩包解压缩
tar -xvf node-v20.10.0-linux-x64.tar.xz
创建软连接
# 创建 npm 软连接
ln -s /home/node-v20.10.0-linux-x64/bin/npm /usr/local/bin
# 创建 node 软连接
ln -s /home/node-v20.10.0-linux-x64/bin/node /usr/local/bin
测试 node 环境是否安装成功?报错!!!
[root@VM-28-17-centos bin]# node -v
node: /lib64/libm.so.6: version `GLIBC_2.27' not found (required by node)
node: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by node)
node: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by node)
node: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by node)
node: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by node)
node: /lib64/libc.so.6: version `GLIBC_2.25' not found (required by node)
使用 strings 命令查看当前 glibc 支持的版本
strings /lib64/libc.so.6 | grep GLIBC_
解决方案:升级 gcc 和 glibc 版本:在升级前备份重要数据,并仔细阅读相关文档和使用说明。
Buffer 中文译为『缓冲区』,是一个类似于 Array 的对象,用于表示固定长度的字节序列。换句话说,Buffer 就是一段固定长度的内存空间,用于处理二进制数据。
alloc
: 这是 Node.js 中的一个函数,用于在堆中分配内存。它通常用于分配一块具有确定大小的连续内存块。node alloc
函数确保了分配的内存是初始化的,也就是说,分配的内存区域都被初始化为零。这使得它非常适合分配需要清零的内存,例如用于密码学目的的内存。然而,由于它涉及到清零操作,node alloc
的性能可能会略低于 allocUnsafe
。
allocUnsafe
: 这是 V8 JavaScript 引擎(Node.js 的默认 JavaScript 引擎)中的一个函数。它用于在 V8 的堆内存中分配内存,不需要进行初始化。这意味着分配的内存区域可能包含以前分配并释放的垃圾数据。因此,使用 allocUnsafe
分配的内存可能存在数据泄露的风险,特别是在处理敏感数据时。然而,由于不需要进行初始化操作,allocUnsafe
的性能通常会比 node alloc
高。
node alloc
和 allocUnsafe
都是用于分配内存的函数,但它们的使用和安全性有所不同。node alloc
提供了初始化的内存分配,适合需要清零的场景,但性能略低。而 allocUnsafe
则提供了未初始化的内存分配,性能较高,但可能存在数据泄露的风险。选择使用哪个函数取决于你的具体需求和安全性要求。
let buf = Buffer.alloc(10);
console.log(buf)
// <Buffer 00 00 00 00 00 00 00 00 00 00>
let buf_2 = Buffer.allocUnsafe(10000);
console.log(buf_2)
// <Buffer 00 06 f5 ff 5b 02 00 00 70 a9 35 f6 5b 02 00 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ... 9950 more bytes>
let buf = Buffer.from("i love you")
console.log(buf)
// <Buffer 69 20 6c 6f 76 65 20 79 6f 75>
Buffer.from()
是 Node.js 的 Buffer
类的一个静态方法,用于创建一个新的 Buffer 实例从指定的 ArrayBuffer,或者在给定的类型数组中。通过
Buffer.from(arrayBuffer[, byteOffset[, length]])
param | detail | default |
---|---|---|
arrayBuffer | 一个 ArrayBuffer 或共享 ArrayBuffer 对象,将创建 Buffer 对象表示的原始二进制数据 | |
byteOffset (可选) | 从 ArrayBuffer 中开始读取数据的偏移量(以字节为单位) | 默认值为 0 |
length (可选) | 要读取的字节数 | 默认值为 arrayBuffer.length - byteOffset |
let buf1 = Buffer.from(new ArrayBuffer(10));
let buf2 = Buffer.from(new ArrayBuffer(10), 2);
// 从偏移 2 开始的数据
let buf3 = Buffer.from(new ArrayBuffer(10), 2, 5);
// 从偏移 2 开始读取 5 个字节的数据
<Buffer 69 20 6c 6f 76 65 20 79 6f 75> 8 bit 8 位存储,两个 16 进制数,00 ~ ff(0 ~ 255)
let buf = Buffer.from("i love you")
buf.forEach(element => {
console.log(element)
// 105 32 108 111 118 101 32 121 111 117
});
let buff = Buffer.from([105, 32, 108, 111, 118, 101, 32, 121, 111, 117])
console.log(buff.toString())
// i love you
let buf = Buffer.from("你好")
console.log(buf)
// <Buffer e4 bd a0 e5 a5 bd>
Buffer类在 Node.js 中用于处理二进制数据,其本身并不直接支持 UTF-8 编码。但是,你可以使用Buffer类来存储和操作 UTF-8 编码的字符串。
例如,如果你有一个 UTF-8 编码的字符串,你可以使用Buffer类的构造函数创建一个Buffer对象:
let buf = Buffer.from('你好,世界!', 'utf-8');
在这个例子中,‘你好,世界!’ 是 UTF-8 编码的字符串,Buffer.from 方法用于创建一个新的 Buffer 对象。第二个参数 ‘utf-8’ 指定了字符串的编码格式。
你也可以使用 Buffer.allocUnsafe() 或 Buffer.from() 来创建一个新的 Buffer 对象,并通过 toString() 方法将 Buffer 对象转换为 UTF-8 编码的字符串:
let buf = Buffer.allocUnsafe(13);
buf.fill('你好,世界!', 0, 13);
let str = buf.toString('utf-8');
console.log(str); // '你好,世界!'
在这个例子中,我们使用 Buffer.allocUnsafe() 创建了一个新的 Buffer 对象,并使用 fill() 方法将字符串填充到 Buffer 中。然后,我们使用 toString() 方法将 Buffer 对象转换为 UTF-8 编码的字符串。
fs 是 Node.js 的一个内置模块,它是 Node.js 文件系统模块,用于在服务器端操作文件。它提供了一系列的方法和属性,可以满足用户对文件的操作需求。例如,可以读取文件、写入文件、删除文件等。
要在 JavaScript 代码中使用 fs 模块来操作文件,需要先导入 fs 模块。可以使用 const fs = require(‘fs’); 来导入该模块。
fs.readFile(path[, options], callback)
:异步地读取文件的内容。path 是文件路径,options 可选,通常不需要指定,callback 是回调函数,它会在文件读取完成后被调用,并包含两个参数:err(错误对象)和 data(文件内容)。
fs.writeFile(path, data[, options], callback)
:异步地将数据写入文件。path 是文件路径,data 是要写入的数据,options 可选,通常不需要指定,callback 是回调函数,它会在文件写入完成后被调用,并包含两个参数:err(错误对象)和 data(写入的数据)。
fs.unlink(path, callback)
:异步地删除文件。path 是要删除的文件路径,callback 是回调函数,它会在文件删除完成后被调用,并包含一个参数:err(错误对象)。
fs.mkdir(path[, options], callback)
:异步地创建目录。path 是要创建的目录路径,options 可选,通常不需要指定,callback 是回调函数,它会在目录创建完成后被调用,并包含一个参数:err(错误对象)。
fs.rename(oldPath, newPath, callback)
:异步地重命名文件或目录。oldPath 是要重命名的文件或目录的路径,newPath 是新的文件或目录的路径,callback 是回调函数,它会在重命名完成后被调用,并包含一个参数:err(错误对象)。
fs.readdir(path[, options], callback)
:异步地读取目录的内容。path 是目录路径,options 可选,通常不需要指定,callback 是回调函数,它会在目录读取完成后被调用,并包含两个参数:err(错误对象)和 files(目录中的文件名列表)。
fs.rmdir(path, callback)
:异步地删除目录。path 是要删除的目录路径,callback 是回调函数,它会在目录删除完成后被调用,并包含一个参数:err(错误对象)。
请注意,这些方法都是异步的,意味着它们不会立即完成。它们通常在回调函数中提供结果,而不是在返回值中提供。因此,需要使用回调函数来处理异步操作的结果。
const fs = require("fs")
const ws = fs.createWriteStream("helloworld.txt")
ws.write("hello world")
ws.end()
Node.Js 流式读写和普通读写的应用场景
普通读写:适用于小数据量、单次读写操作。例如,读取文件内容并在控制台输出,或者将数据写入文件。
const fs = require("fs")
fs.readFile("helloworld.txt", (err, data) => {
if (err) {
console.log(err)
} else {
console.log(data.toString())
}
})
流式读写:适用于处理大量数据、高并发场景。例如,从网络中读取数据,或者将数据写入到网络中。在流式读写中,数据是按块读取或写入的,而不是一次性加载到内存中,这使得它能够处理大量数据,同时减少内存消耗。
const fs = require("fs")
const rs = fs.createReadStream("helloworld.txt")
rs.on('data', chunk => {
console.log(chunk.toString())
})
在Node.js中,文件系统(fs)模块提供了流式拷贝和普通拷贝两种方式。
普通拷贝(fs.readFile和fs.writeFile)是同步的,它们在执行期间会阻塞其他操作,直到整个文件被读取或写入完毕。这种方式适用于小型文件的拷贝,因为它相对简单且易于理解。但是,对于大型文件,普通拷贝可能会导致性能问题,因为它需要一次性将整个文件读入内存或写入磁盘。
流式拷贝(fs.createReadStream和fs.createWriteStream)则是异步的,它们使用了流(Stream)的概念。流是一种可以用于读取或写入数据的通道,它们可以以较小的数据块为单位进行读写,而不需要一次性读取整个文件。这种方式适用于大型文件的拷贝,因为它可以避免一次性读入整个文件而导致的内存占用问题。
流式拷贝
const fs = require('fs')
const process = require('process')
const rs = fs.createReadStream("assets/test.mp4")
const ws = fs.createWriteStream("test_new.mp4")
rs.on("data", chunk => {
console.log(chunk)
ws.write(chunk)
// 65486 more bytes
})
rs.on('end', () => {
console.log(process.memoryUsage())
})
process.memoryUsage() 是 Node.js 中的一个函数,用于返回当前 Node.js 进程的内存使用情况。这个函数返回一个对象,其中包含了 Node.js 进程使用的各种内存资源的使用情况。这些值可以帮助你了解你的 Node.js 进程的内存使用情况,以便于优化你的代码或诊断内存泄漏等问题。
返回的对象属性
obj | detail |
---|---|
rss | Resident Set Size,这是进程在主内存中(即 RAM)占用的空间量,以字节为单位。 |
heapTotal | V8 引擎已申请的堆内存总量,以字节为单位。 |
heapUsed | V8 引擎已使用的堆内存量,以字节为单位。 |
external | 进程使用的外部内存,以字节为单位。 |
{
rss: 20463616, // 20463616 / 1024 / 1024 = 19 MB
heapTotal: 4866048,
heapUsed: 4144648,
external: 281354,
arrayBuffers: 11146
}
普通拷贝示例
const fs = require('fs');
fs.readFile('source.txt', 'utf8', (err, data) => {
if (err) throw err;
fs.writeFile('destination.txt', data, (err) => {
if (err) throw err;
console.log('File has been saved!');
});
});
const fs = require("fs")
fs.stat("test_new.mp4", (err, stat) => {
if (err) {
console.log(err)
} else {
console.log(stat)
console.log(stat.isFile())
}
})
obj method | return value type |
---|---|
stats.size | 文件大小,以字节为单位。 |
stats.mtime | 文件修改时间,是一个 Date 对象。 |
stats.ctime | 文件创建时间,是一个 Date 对象。 |
stats.atime | 文件访问时间,是一个 Date 对象。 |
stats.birthtime | 文件的出生时间,是一个 Date 对象(在某些系统上可能不可用)。 |
stats.uid | 文件的用户 ID。 |
stats.gid | 文件的组 ID。 |
stats.mode | 文件的权限模式。 |
stats.ino | 文件的 inode 号码。 |
stats.dev | 文件的设备号码。 |
stats.nlink | 文件的硬链接数量。 |
stats.isFile() | 如果这是一个文件,返回 true。 |
stats.isDirectory() | 如果这是一个目录,返回 true。 |
stats.isBlockDevice() | 如果这是一个块设备,返回 true。 |
stats.isCharacterDevice() | 如果这是一个字符设备,返回 true。 |
stats.isSymbolicLink() | 如果这是一个符号链接,返回 true(只在 Unix 系统中有效)。 |
stats.isFIFO() | 如果这是一个 FIFO(命名管道),返回 true。 |
stats.isSocket() | 如果这是一个套接字,返回 true。 |
Stats { dev: 810007100, mode: 33206, nlink: 1, uid: 0, gid: 0, rdev: 0, blksize: 4096, ino: 1407374883944336, size: 57077833, blocks: 111488, atimeMs: 1698839970416.1738, mtimeMs: 1698839970416.1738, ctimeMs: 1698839970416.1738, birthtimeMs: 1698839007835.6604, atime: 2023-11-01T11:59:30.416Z, mtime: 2023-11-01T11:59:30.416Z, ctime: 2023-11-01T11:59:30.416Z, birthtime: 2023-11-01T11:43:27.836Z }
在Node.js中,__dirname
是一个全局变量,表示当前正在执行的脚本所在的目录路径。它是一个字符串(String)类型的值,包含了当前脚本所在的目录路径。
这个变量在Node.js中非常有用,因为它可以帮助你在脚本中引用当前目录或子目录中的文件或模块。通过使用__dirname
变量,你可以构建相对路径来引用其他文件或模块,或者执行一些与当前目录相关的操作。
console.log(__dirname)
HTTP(Hypertext Transfer Protocol)是一种用于在网络上传输数据的协议,它定义了客户端与服务器之间的通信规则。HTTP协议基于请求/响应模型,客户端向服务器发送请求,服务器响应请求并返回数据。HTTP协议使用明文的方式传输内容,因此不适合传输敏感信息。HTTP协议的版本主要有HTTP/1.0和HTTP/1.1,其中HTTP/1.1是目前最常用的版本。
HTTP协议的特点是简单、灵活、无连接和无状态。简单是指协议的结构简单,易于理解和实现;灵活是指协议具有良好的扩展性,可以在不改变核心协议的情况下添加新的功能;无连接是指每次请求都需要建立连接,而无状态是指服务器不会为每个请求保持状态。
在计算机科学和网络编程中,request 和 response 是HTTP协议中的核心概念。它们分别表示客户端向服务器发送的请求和服务器对请求的响应。
HTTP请求(request)是由客户端(通常是Web浏览器)向服务器发送的,用于请求访问网页或资源。
方法(GET、POST、PUT、DELETE等)
请求URL(资源的路径和名称)
请求头(header),包含关于请求的附加信息,如内容类型(Content-Type)、字符集(Charset)等
请求体(body),包含要发送的数据,如表单数据或JSON数据等
HTTP响应(response)是由服务器对客户端发送的请求进行响应的结果。
状态码(status code),表示请求的处理结果,如200表示成功,404表示未找到资源等
响应头(header),包含关于响应的附加信息,如内容类型(Content-Type)、字符集(Charset)等
响应体(body),包含服务器返回的数据,如网页内容、JSON数据等
在Web开发中,HTTP请求和响应是实现客户端与服务器之间通信的关键。通过发送HTTP请求来获取网页或资源,并接收HTTP响应来获取结果。
const http = require("http")
const server = http.createServer((request, response) => {
console.log(request.method)
response.setHeader("content-type", "text/html;charset=utf-8")
response.end("唤醒手腕")
})
server.listen(9000, ()=> {
console.log("server run")
})
在 Node.js 中,URL 是一个内置对象,用于表示一个 URL,它包含一系列用于解析和操作 URL 的属性和方法。您可以使用 new URL() 构造函数创建一个新的 URL 对象。
创建 URL 对象的示例:
const url = new URL('https://www.example.com/path/to/page.html');
在这个示例中,我们使用 new URL() 构造函数创建一个新的 URL 对象,并将一个字符串参数传递给它,该字符串表示要创建的 URL。这个构造函数将解析这个字符串,并创建一个新的 URL 对象,该对象表示相同的 URL。还可以使用 URL 构造函数从现有 URL 创建一个新的 URL 对象。
const baseUrl = new URL('https://www.example.com/');
const pageUrl = new URL('/path/to/page.html', baseUrl);
在这个示例中,我们首先创建一个表示基本 URL 的 URL 对象(baseUrl),然后使用 new URL() 构造函数创建一个新的 URL 对象(pageUrl),该对象表示相对于基本 URL 的相对 URL。
请注意,在 Node.js 中,尽管 URL 是一个内置对象,但它并不包含在 Node.js 的核心 API 中。相反,它是在 Node.js 的标准库中定义的。
const http = require("http")
const fs = require("fs")
const server = http.createServer((request, response) => {
const url = new URL(request.url, "http://127.0.0.1:9000")
console.log(url)
response.end("hello world")
})
server.listen(9000, ()=> {
console.log("run")
})
URL {
href: 'http://127.0.0.1:9000/favicon.ico',
origin: 'http://127.0.0.1:9000',
protocol: 'http:',
username: '',
password: '',
host: '127.0.0.1:9000',
hostname: '127.0.0.1',
port: '9000',
pathname: '/favicon.ico',
search: '',
searchParams: URLSearchParams {},
hash: ''
}
Node.js 模块化是指将代码分解成独立、可重用的模块,以便更好地组织和管理代码。在 Node.js 中,模块是一种封装代码的方式,可以将其作为单独的文件存在,然后在其他文件中引入和使用。Node.js 使用 CommonJS 模块规范,即使用 require() 函数来引入模块,使用 module.exports 导出模块。
在Node.js中,exports和module.exports都是模块导出对象的属性,用于定义模块导出的内容。但是它们在导出方式和使用上有一些区别。
exports是一个指向module.exports的引用,默认情况下,它和module.exports指向同一个对象。在模块内部,可以通过修改exports指向的内容来改变模块导出的内容。
exports.sayHello = function() {
console.log('Hello from module!');
};
var myModule = require('./myModule');
myModule.sayHello();
module.exports是模块导出的真正接口,它允许你定义模块导出的主要功能或对象。当一个模块被导入时,Node.js会执行该模块的代码,并将module.exports属性暴露给导入该模块的代码。
需要注意的是,如果你同时使用了exports和module.exports来导出内容,那么exports将不再指向module.exports。在这种情况下,你应该谨慎使用这两个属性,以避免混淆和冲突。
历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。这对开发大型的、复杂的项目形成了巨大障碍。
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
语法上面,CommonJS 模块使用 require() 加载和 module.exports 输出,ES6 模块使用 import 和 export。用法上面,require()是同步加载,后面的代码必须等待这个命令执行完,才会执行。import命令则是异步加载,或者更准确地说,ES6 模块有一个独立的静态解析阶段,依赖关系的分析是在那个阶段完成的,最底层的模块第一个执行。
package.json 配置开启 ES6
"type": "module"
ES6 import 命令加载
ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,再通过 import 命令输入。下面代码的实质是从fs模块加载 3 个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。当然,这也导致了没法引用 ES6 模块本身,因为它不是对象。
import { stat, exists, readFile } from 'fs';
npm(Node Package Manager):npm 是随同 Node.js 安装的默认包管理器,它使开发者可以方便地查找、安装、更新和删除 Node.js 模块。npm 已经成为了非官方的发布 Node 模块(包)的标准。
yarn:Yarn 是一个由 Facebook 开发并开源的 JavaScript 包管理器,用于在 JavaScript 项目中管理依赖项。它与 npm 和其他包管理器有很多相似之处,但也有一些独特的特性。
pnpm:pnpm 是一个高效的 JavaScript 包管理器,旨在加快项目依赖项的安装速度。它是建立在 npm 的基础之上的,但通过一些改进,使得在处理大型项目时能够提供更好的性能。
npm init 是 npm 命令行工具的一个命令,用于创建一个新的 Node.js 项目。运行 npm init 命令后,会启动一个交互式命令行界面,提示您输入一些项目的相关信息,如项目名称、版本号、描述等。这些信息将被用于创建一个 package.json 文件,该文件包含了项目的元数据和依赖项信息。
-y:自动接受默认值并生成 package.json 文件。
-q:以非交互式模式运行,直接输出生成的 package.json 文件内容。
-w:指定生成的 package.json 文件的路径。
内置模块
:Node.js 首先尝试查找是否为内置模块,这些模块是 Node.js 自带的,无需安装即可使用,例如 http、fs 和 path 等。
文件模块
:如果模块不是内置模块,Node.js 将尝试查找文件模块。文件模块可以是相对路径的文件模块(以./或…/开头)、绝对路径的文件模块(以/开头)或者目录作为模块(以./dirname形式)。
目录模块
:如果使用了目录作为模块名,并且目录中包含一个package.json文件,则 Node.js 会查找该文件中指定的main入口文件。如果package.json不存在或者未指定main,则 Node.js 会尝试加载目录下的 index.js 或 index.node 文件作为入口。
非原生模块
:如果以上查找都没有找到模块,Node.js 会将模块名解析为绝对路径,并按照一定的路径顺序在文件系统中查找 node_modules 目录。Node.js 会从当前模块的目录开始查找,然后逐级向上查找父目录的 node_modules,直到根目录。如果找到了 node_modules 目录,则进入其中查找对应模块。
在 package.json 文件中添加 "package"
字段,然后运行 npm install。在 “package” 字段中,可以指定需要全局安装的包,例如"package": {“name”: “my-app”, “version”: “1.0.0”, “dependencies”: {“webpack”: “^5.0.0”}}。运行npm install后,将会全局安装指定的包。
直接使用命令 npm install -g 包名。
npm install -g webpack
配置 npm 全局安装地址
创建一个新的目录来存储全局安装的包。例如,可以在D盘下创建一个名为“npm-global”的目录。更新npm配置以设置新的全局安装路径。打开命令行或终端,并输入配置命令。这会将全局安装路径设置为D盘下的“npm-global”目录。
npm config set prefix 'D:\npm-global'
添加新的路径到系统的 PATH 环境变量。这一步可能因操作系统而异。在 Windows 中,打开系统属性(右键点击“计算机”,选择“属性”,然后点击“高级系统设置”)。点击“环境变量”按钮。在“系统变量”部分,找到名为“Path”的变量,点击“编辑”。在“变量值”中,将新的路径添加到已有的路径列表末尾。如果列表中没有其他路径,可以直接将整个“D:\npm-global”添加到“变量值”中。确认并保存所有对话框。npm 将使用新的全局安装路径来存储其安装的包。
npm run 是 npm 命令行中的一个重要特性,它允许你在 package.json 文件中定义的脚本字段中运行命令。使用npm run script执行脚本的时候都会创建一个shell,然后在shell中执行指定的脚本。
npm start 和 npm run 区别
npm start 是 npm 的内置命令,用于启动项目。它会在项目的根目录下寻找package.json文件,并且在该文件中查找 scripts 字段中的 start 命令。如果找到了该命令,就会执行该命令来启动项目,否则会报错。
"scripts": {
"start": "node index.js",
"serve": "node index.js"
}
npm run 是 npm 的内置命令,用于运行package.json文件中的自定义脚本。它的语法是 npm run script_name,其中 script_name 是在 package.json 文件中定义的脚本名称。和 npm start 不同的是,npm run 可以运行除了 start 以外的其他自定义脚本,而且必须显式地指定脚本名称。 总之,npm start 是一个特殊的、内置的命令,用于启动项目;而 npm run 则是一个通用的命令,用于运行自定义脚本。
npm run 特性说明
自动添加node_modules/.bin到PATH
:npm run命令会自动在环境变量$PATH添加node_modules/.bin目录。这意味着当你在scripts字段中调用命令时,不需要加上完整的路径,从而避免了全局安装NPM模块。
列出可执行脚本命令
:如果npm run命令后面没有加上任何参数,直接运行,会列出package.json里面所有可以执行的脚本命令。
命令简写:npm内置了两个命令简写,npm test等同于执行npm run test,npm start等同于执行npm run start。
运行特定脚本
:你可以通过在npm run命令后加上要运行的脚本名称来执行特定的脚本。例如,npm run lint会执行package.json中定义的lint脚本。
创建Shell并执行命令
:npm run会创建一个Shell,并执行指定的命令。同时,它会临时将node_modules/.bin加入PATH变量,这意味着本地模块可以直接运行。
nvm 的全名是 Node Version Manager,是一个用于管理 Node.js 版本的工具。它主要通过命令行实现,可以实现在同一台机器上安装和切换不同版本的Node.js。
nvm 的主要功能包括安装和卸载Node.js的不同版本,切换不同版本的 Node.js,管理全局和本地的Node.js 模块等。它支持在不同的操作系统上使用,使得开发者可以方便地在同一台机器上开发和测试不同 Node.js 应用程序,不必在不同的机器上安装不同的 Node.js 版本。
要使用nvm,需要先下载并安装脚本,然后在命令行中输入相应的命令即可完成Node.js版本的安装、卸载和切换等操作。
nvm 版本管理器安装
npm install -g nvm
npm registry manager(即:指的是‘npm’的镜像源管理工具)可以快速地在 npm 源间切换。
安装 nrm 全局安装 nrm
npm install -g nrm
nrm 查看可选择的源
nrm ls
nrm 切换镜像源
nrm use <源名>
设置镜像(淘宝镜像最新地址)
npm config set registry https://registry.npmmirror.com
还原镜像地址为默认地址
npm config set registry https://registry.npmjs.org/
获取镜像地址
npm config get registry
C:\Users\Administrator>npm config list
; "builtin" config from E:\Environment\NodeJs-16.10.0\node_modules\npm\npmrc
; prefix = "C:\\Users\\Administrator\\AppData\\Roaming\\npm" ; overridden by user
; "user" config from C:\Users\Administrator\.npmrc
cache = "E:\\Environment\\NodeJs-16.10.0\\node_cache"
prefix = "E:\\Environment\\NodeJs-16.10.0\\node_global"
registry = "https://registry.npmjs.org/"
; node bin location = E:\Environment\NodeJs-16.10.0\node.exe
; cwd = C:\Users\Administrator
; HOME = C:\Users\Administrator
; Run `npm config ls -l` to show all defaults.
常见 npm config 配置
npm config set <key>=<value> [<key>=<value> ...]
npm config get [<key> [<key> ...]]
npm config delete <key> [<key> ...]
npm config list [--json]
npm config edit
在 .nmprc 文件直接在里面配置同样可以实现
配置 node_global 和 node_cache 系统环境变量
测试下载 cnpm 解析过程
npm config set registry https://registry.npmmirror.com
npm install cnpm -g
注意在 cnpm 下载完成之后会在配置的 node_global 目录生成 cnpm cmd 命令脚本,资源文件会在当前目录下 node_modules 目录下。因为配置了当前目录的环境变量,所以在任何的目录下,执行 cnpm 都可以直接运行。
module | 简介 |
---|---|
Express.js | 一个快速、简单的 Node.js Web 应用框架,可以帮助你构建高效的 Web 服务器。 |
Node.js 内置模块 | Node.js 自带了许多内置模块,例如 http、fs、path、os 等,用于处理 HTTP 请求、文件系统操作、路径处理、操作系统相关功能等。 |
Request | 一个简单易用的 HTTP 请求库,可以方便地发送 GET 和 POST 请求,并支持设置请求头和响应头等信息。 |
Bluebird | 一个功能强大的 JavaScript 库,提供 Promise API,用于处理异步操作和回调函数。 |
Lodash | 一个 JavaScript 实用工具库,提供许多常用的函数和方法,如数组操作、对象操作、字符串操作、工具函数等。 |
Mongoose | 一个 MongoDB 对象模型工具,提供了一种易于使用的 API,用于在 Node.js 中连接和操作 MongoDB 数据库。 |
Passport.js | 一个用于 Node.js 的身份验证中间件,提供了多种身份验证策略,在这里插入代码片 如本地用户名密码验证、OAuth 2.0 等。 |
Socket.IO | 一个基于 Node.js 的实时应用程序框架,提供了实时、双向和基于事件的通信能力。 |
Express-Validator | 一个 Express.js 插件,用于对请求数据进行验证和过滤,以确保数据的安全性和完整性。 |
JWT(JSON Web Token) | 一种用于身份验证和授权的开放标准,可以在不同的应用程序之间安全地传输信息。 |
readline是Node.js里实现标准输入输出的封装好的模块,通过这个模块我们可以以逐行的方式读取数据流。readline 模块提供了用于从可读流(例如 process.stdin)每次一行地读取数据的接口。
const readline = require('readline');
const shell = readline.createInterface({
input: process.stdin,
output: process.stdout
});
Interface类 继承自: < EventEmitter >
readline.Interface 类的实例是使用 readline.createInterface() 方法构造的。 每个实例都与单个 input 可读流和单个 output 可写流相关联。 output 流用于打印到达并从 input 流中读取的用户输入的提示。
生成 .env 案例
const readline = require('readline') const fs = require('fs') let shell = readline.createInterface({ input: process.stdin, output: process.stdout }); shell.question('Please Input OPENAI-API-KEY: ', answer => { const env = 'OPENAI_API_KEY=' + answer fs.writeFile(".env", env, err => { if (err) { console.log("Config Failed: Input Data In Error"); } else { console.log("Config Successful: Create `.env` File"); pause() } }) }); shell.on('close', () => { process.exit(0); }); function pause() { shell.question('Press Enter to continue...', () => { shell.close(); }); }
This library provides convenient access to the OpenAI REST API from TypeScript or JavaScript. It is generated from our OpenAPI specification with Stainless. To learn how to use the OpenAI API, check out our API Reference and Documentation.
import readline from 'readline' import { config } from 'dotenv' import OpenAI from 'openai'; config() const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); const chat = async (input) => { const chatCompletion = await openai.chat.completions.create({ messages: [{ role: 'user', content: 'Say this is a test' }], model: 'gpt-3.5-turbo', }); return chatCompletion } const shell = readline.createInterface({ input: process.stdin, output: process.stdout }); shell.prompt() shell.on('line', async (input) => { console.log(await chat(input)) shell.prompt() })
运行结果
> hello
{
id: 'chatcmpl-8Hq58Ew6LCYgQCMVknbmyGdVyKj6T',
object: 'chat.completion',
created: 1699262470,
model: 'gpt-3.5-turbo-0613',
choices: [ { index: 0, message: [Object], finish_reason: 'stop' } ],
usage: { prompt_tokens: 12, completion_tokens: 5, total_tokens: 17 }
}
chatCompletion.choices[0].message.content
使用服务器发送事件(SSE)为流式响应提供支持
流式响应是指在 HTTP 或其他网络协议中,响应的内容以流的形式逐步传输给客户端,而不是一次性将整个响应体传输过来。这对于处理大型数据或实时数据流非常有用,因为它允许客户端逐步处理数据而无需等待整个响应完成。
在Node.js中,你可以使用可读流(Readable Stream)来处理流式响应。例如,如果使用 Axios 库进行 HTTP 请求,可以通过设置响应数据的处理方式为流,而不是在内存中缓存整个响应。
const axios = require('axios'); const apiUrl = 'https://example.com/streaming-endpoint'; axios.get(apiUrl, { responseType: 'stream' }) .then(response => { response.data.on('data', chunk => { console.log(chunk.toString()); }); response.data.on('end', () => { console.log('Stream ended'); }); }) .catch(error => { console.error('Error:', error.response ? error.response.data : error.message); });
openai 流式请求结束
import OpenAI from 'openai'; import { config } from 'dotenv'; config() const openai = new OpenAI({ apiKey: process.env["OPENAI_API_KEY"], }); async function main() { const stream = await openai.chat.completions.create({ model: 'gpt-3.5-turbo', messages: [{ role: 'user', content: '背诵《静夜思》' }], stream: true, }); for await (const part of stream) { process.stdout.write(part.choices[0]?.delta?.content || ''); } } main();
安装 node-schedule
npm install node-schedule
创建一个新的 Node.js 文件(例如 scheduler.js)
const schedule = require('node-schedule');
schedule.scheduleJob('0 8 * * *', function() {
console.log('早上好!');
});
console.log('定时任务已启动...');
在上面的代码中,‘0 8 * * *’ 是一个 cron 风格的时间表达式,表示每天的 8:00。
请注意,这个程序必须保持运行状态,以便在指定的时间执行任务。如果你关闭了程序或服务器,任务就不会被执行。如果你想在后台运行这个程序并确保它始终运行,可以考虑使用像 pm2 这样的工具。
Job 对象详细信息
<ref *1> Job { pendingInvocations: [ Invocation { job: [Circular *1], fireDate: [CronDate], endDate: undefined, recurrenceRule: [CronExpression], timerID: [Timeout] } ], job: [Function (anonymous)], callback: false, running: 0, name: '<Anonymous Job 1 2023-11-07T05:55:48.994Z>', trackInvocation: [Function (anonymous)], stopTrackingInvocation: [Function (anonymous)], triggeredJobs: [Function (anonymous)], setTriggeredJobs: [Function (anonymous)], deleteFromSchedule: [Function (anonymous)], cancel: [Function (anonymous)], cancelNext: [Function (anonymous)], reschedule: [Function (anonymous)], nextInvocation: [Function (anonymous)] }
cron 风格 时间表达式
* * * * * *
┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ │
│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
│ │ │ │ └───── month (1 - 12)
│ │ │ └────────── day of month (1 - 31)
│ │ └─────────────── hour (0 - 23)
│ └──────────────────── minute (0 - 59)
└───────────────────────── second (0 - 59, OPTIONAL)
使用 new Date 配置时间
const schedule = require('node-schedule');
const date = new Date(2023, 11, 7, 12, 30, 0);
const job = schedule.scheduleJob(date, function(){
console.log('The world is going to end today.');
});
const job = schedule.scheduleJob({hour: 14, minute: 30, dayOfWeek: 0}, function(){
console.log('Time for tea!');
});
周期执行案例
占位符 | 说明 |
---|---|
* | 表示通配符,匹配该域的任意值,假如在 Minutes 域使用 * 表示每分钟都会触发事件。 |
? | 只能用在 DayofMonth 和 DayofWeek 两个域。因为 DayofMonth 和 DayofWeek 会相互影响。例如想在每月的 20 日触发调度,不管 20 日到底是星期几,则只能使用如下写法: 13 13 15 20 * ? , 其中最后一位只能用 ? ,而不能使用 * ,如果使用 * 表示不管星期几都会触发,实际上并不是这样。 |
- | 表示范围,例如 在 Minutes 域使用 5-20,表示从5分到20分钟每分钟触发一次。 |
/ | 表示起始时间开始触发,然后每隔固定时间触发一次,如在 Minutes 域使用 5/20 表示5分钟触发一次,而 25,45 等分别触发一次。 |
, | 表示枚举值,如在 Minutes 域使用 5, 20 ,表示在 5 和 20 分每分钟触发一次。 |
注意:由于月份中的日期和星期中的日期这两个元素互斥,要对其中一个设置 ?
const schedule = require('node-schedule');
const job = schedule.scheduleJob('*/5 * * * * *', function (fireDate) {
console.log('This job was supposed to run at ' + fireDate + ', but actually ran at ' + new Date());
});
配置 开始时间 和 结束时间
const startTime = new Date(Date.now() + 5000);
const endTime = new Date(startTime.getTime() + 5000);
const job = schedule.scheduleJob({ start: startTime, end: endTime, rule: '*/1 * * * * *' }, function(){
console.log('Time for tea!');
});
要在后台运行 Node.js 程序并确保它持续运行,pm2
是一个非常受欢迎的选择。pm2
是一个运行时守护程序,它可以帮助您管理和保持应用程序在线。
npm 全局安装 pm2
首先,您需要全局安装 pm2
:
npm install pm2 -g
2. 使用 pm2 启动你的程序
假设您的程序文件名是 app.js
执行命令启动:
pm2 start app.js
这将在后台启动您的程序并由 pm2
守护。指定一个名称:
pm2 start app.js --name "my-app-name"
3. 其他有用的 pm2 命令
- 查看所有运行的进程:pm2 list
- 查看某个应用的日志:pm2 logs "my-app-name"
- 停止应用:pm2 stop "my-app-name"
- 重新启动应用: pm2 restart "my-app-name"
- 删除应用: pm2 delete "my-app-name"
4. 设置开机启动
如果你想要在服务器重启后自动启动你的 Node.js 程序,你可以使用 pm2
的开机启动脚本功能。首先,保存当前的进程列表:pm2 save
。然后为您的操作系统生成并设置启动脚本:pm2 startup
这将显示一个你需要手动运行的命令。复制并运行该命令以完成设置。现在,即使服务器重启,pm2
也会确保您的 Node.js 程序继续运行。总之,pm2
提供了一个强大和方便的方式来在后台管理和运行 Node.js 程序。
Node qrcode 图片二维码
Node qrcode 是一个在 Node.js 中生成二维码的库。它可以通过 npm 进行安装,安装命令为 npm install qrcode。安装完成后,可以通过 API 生成二维码。
const fs = require('fs');
const qrcode = require('qrcode');
const data = 'Hello, QR Code!';
qrcode.toFile('qrcode.png', data, (err) => {
if (err) throw err;
console.log('二维码已生成并保存为qrcode.png');
});
配置 QRCODE 属性值
const fs = require('fs'); const qrcode = require('qrcode'); const data = 'Hello, QR Code!'; const options = { errorCorrectionLevel: 'H', version: 10, color: { dark: '#F9BF18', light: '#0F0D23', }, margin: 4, scale: 4, }; qrcode.toFile('qrcode.png', data, options, (err) => { if (err) throw err; console.log('二维码已生成并保存为qrcode.png'); });
errorCorrectionLevel 容错级别:‘L’, ‘M’, ‘Q’, ‘H’( 默认是 ‘H’ )
qrcode-terminal 终端二维码
qrcode-terminal 是一个用于在终端(命令行界面)中生成和显示二维码的Node.js库。它可以让你轻松地在终端中显示文本或链接的二维码。
确保你的项目中已经安装了 qrcode-terminal 库。
npm install qrcode-terminal
编写一个 Node.js 脚本来生成和显示二维码。使用 { small: true } 选项可以生成较小的二维码,适用于终端显示。运行脚本后,你将在终端中看到生成的二维码,可以使用终端扫描或查看。
const qrcode = require('qrcode-terminal');
const text = 'https://www.example.com';
qrcode.generate(text, { small: true });
dotenv
是一个Node.js库,用于从一个名为 .env
的配置文件中加载环境变量到Node.js应用程序中。它可以帮助你在不同环境中轻松地管理应用程序的配置信息,而不必硬编码这些信息到你的代码中。
以下是如何在Node.js中使用 dotenv
:
安装 dotenv
库:使用 npm 或者 yarn 安装 dotenv
库
npm install dotenv
创建一个名为 .env
的配置文件并在其中定义环境变量。请注意,.env
文件中的每一行都包含一个键值对,使用等号(=)分隔键和值。
DB_HOST=localhost
DB_PORT=5432
API_KEY=your-api-key
在你的Node.js应用程序中,使用 dotenv
加载 .env
文件中的环境变量。通常,在应用程序的入口文件中执行这个操作,例如 app.js
或 server.js
。
require('dotenv').config();
const dbHost = process.env.DB_HOST;
const dbPort = process.env.DB_PORT;
const apiKey = process.env.API_KEY;
现在你可以在你的应用程序中使用 process.env
对象来访问从 .env
文件中加载的环境变量。这样你就可以避免在代码中硬编码敏感信息,也更容易在不同环境中管理配置。
请确保在 .env
文件中存储敏感信息(如API密钥或数据库凭证)时要保持安全,不要将该文件上传到版本控制系统,因为它包含敏感信息。通常,你会在 .gitignore
文件中添加 .env
来确保它不会被提交到代码仓库中。
在Node.js中,你可以使用第三方库来创建系统弹窗或消息框。一个常用的库是 node-notifier,它允许你在不同平台上创建通知和弹窗。将创建一个简单的系统通知(弹窗),其中包含标题和消息。你可以根据需要添加其他选项,如通知图标、声音等。
const notifier = require('node-notifier');
notifier.notify({
title: '通知标题',
message: '这是一个系统弹窗示例',
icon: 'favicon.ico',
sound: true,
});
notifier.on('click', function (notifierObject, options) {
console.log('通知被点击了!');
});
node-notifier 测试结果
在 Node.js 中实现自动关机通常需要依赖操作系统的特定命令或工具,因为自动关机涉及到操作系统级别的控制。在 Node.js 中实现自动关机的方法,使用 child_process 模块来执行操作系统的关机 Command。
const { exec } = require('child_process'); let shutdownCommand = ''; if (process.platform === 'win32') { shutdownCommand = 'shutdown /s /t 1'; } else if (process.platform === 'linux' || process.platform === 'darwin') { shutdownCommand = 'shutdown -h now'; } else { console.error('不支持的操作系统'); process.exit(1); } exec(shutdownCommand, (error, stdout, stderr) => { if (error) { console.error(`执行关机命令时出错: ${error.message}`); return; } console.log(`操作系统返回: ${stdout}`); });
请注意,上述代码中的关机命令根据不同的操作系统有所不同。在 Windows 上,我们使用 shutdown 命令,而在 Linux 和 macOS 上,我们使用 shutdown 命令。在运行这段代码之前,请确保你的程序有足够的权限来执行关机操作,否则可能会失败。另外,自动关机是一项敏感的操作,请谨慎使用,并确保你真的需要它。
如果你需要实现更复杂的自动关机功能,例如在特定时间或条件下执行关机操作,你可能需要编写更复杂的 Node.js 应用程序来管理这些条件和计时器。
Node.js 是一个基于 JavaScript 的开源、跨平台的运行环境,主要用于服务器端开发。虽然 JavaScript 是一种面向对象的编程语言,但 Node.js 的核心 API 是基于模块的,而不是面向对象的。然而,您可以在 Node.js 中使用面向对象编程(OOP)的方式开发代码。
在 JavaScript 中,您可以使用构造函数、原型链、类等不同的方式来创建和组织对象。在 Node.js 中,您可以使用这些特性来编写面向对象的代码。
ES6 规范中已经有明确定义类的关键字 class 了,那我们今天就使用新的 ES6 规范来创建类以及实例化我们类的对象。
class Animal {
constructor(name, hairColor) {
this.name = name;
this.hairColor = hairColor;
}
eat() {
console.log(`我叫${this.name}, 我正在吃饭饭`)
}
sleep() {
console.log(`我叫${this.name}, 我正在睡觉觉`)
}
}
在早期我们常常通过原型的方式来创建类
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function () {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
};
const person = new Person('Alice', 25);
person.sayHello();
在Node.js中,"class static"是指一种在类级别上定义的方法或属性,可以在创建类的实例时直接访问,而不需要先实例化类。这些方法或属性不属于类的任何特定实例,而是属于类本身。
可以使用静态方法或属性来定义类级别的行为,这些方法或属性可以在类的任何实例上直接调用,而不需要先实例化类。这对于需要在多个实例之间共享某些行为或数据的情况非常有用。
class MyClass {
static myStaticProperty = 'This is a static property';
static myStaticMethod() {
console.log('This is a static method');
}
}
我们可以通过 MyClass.myStaticMethod() 的方式直接调用该静态方法,而不需要先实例化类。除了静态方法之外,Node.js还支持静态属性。静态属性可以在类的所有实例之间共享数据,而不需要将数据存储在每个实例中。
在其中定义了一个名为 myStaticProperty 的静态属性。我们可以使用 MyClass.myStaticProperty 的方式直接访问该静态属性,而不需要先实例化类。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。