当前位置: 首页 > news >正文

前端宝典十二:node基础模块和常用API

Node.js是开源、跨平台的JavaScript运行时环境,构建在Chromev8引擎之上。
Node.js是异步事件驱动单线程模型。
由于Node.js是异步非阻塞的特性,因此适用于I/O密集型应用场景。
需要注意的是,Node.js是单线程模型,需要避免CPU的耗时操作。

Node.js版本的特点:

  • Current 版本:包含了主分支上非重大的更新。
  • Active LTS 版本:经过 团队审核的新功能、错误修复和更新,已被确定为适用于发布线且稳
    定。
  • Maintenance 版本:关键错误修复和安全更新。

建议: 由于偶数版本获得的支持时间比较⻓,推荐在生产环境中使用偶数版本的 Node.js 。

一、CommonJs模块

Node.js应用由模块组成,默认采用的是 CommonJS 规范。即每个文件是一个模块,有自己的作 用域。在一个文件里面定义的变量、函数、类等都是私有的,对其它文件不可⻅。
不过我们可以通过在模块中通过 exports 或者 module.exports 命令将内容导出,其它文件就可 以通过 require 命令访问到这些被导出的内容。

  • module: 是对当前模块对象的引用。 module.exports 用于定义模块导出的内容。
  • exports: 是 对应的引用。
  • require: 加载模块,访问模块导出的内容,多次加载模块使用缓存数据,第二次加载时直接返回上一次的缓存结果。
  • __dirname: 当前模块的文件夹路径
  • __filename: 当前模块的文件路径。
  • require.cache:存储已加载的模块的缓存对象
  • require.main:主入口文件模块对象
  • require.resolve:返回模块解析后的文件路径

Node.js会检测出当前代码是否存在循环引用,并做相应的处理,如抛出warning

二、ECMAScript模块

ECMAScript Module( ESM)是打包Javascript代码以供重复使用的官方标准格式。模块是使用importexport 相关的语句定义的。

ECMAScript和CommonJs区别

  1. ESM没有 require 、 exports 、 module.exports ,使用的是import、export
  2. ESM没有 __filename 、 __dirname 。
  3. ESM没有 require.resolve ,不过可以使用 import.meta.resolve 。
  4. ESM没有 require.cache 。

三、API

1、module.builtinModules

用于验证是否是由第三方维护

const builtin = require('node:module').builtinModules;

2、module.createRequire(filename)

创建 require 函数。 参数必须是URL对象、 字符串,或者是绝对路径。

3、module.isBuiltin(moduleName)

检测模块是否是内置模块。

const isBuiltin = require('node:module').isBuiltin; 
console.log(isBuiltin('node:path')); // true
console.log(isBuiltin('path')); // true
console.log(isBuiltin('wss')); // false

4、URL模块

URL模块提供了一些非常实用的用于解析 的方法。

1. new URL()

const url = require('node:url');
const myURL = new URL('https://user:pass@sub.example.com:8080/p/a/t/h?query=string#hash')
/*href: 'https://user:pass@sub.example.com:8080/p/a/t/h?query=string#hash',origin: 'https://sub.example.com:8080',protocol: 'https:',username: 'user',password: 'pass',host: 'sub.example.com:8080',hostname: 'sub.example.com',port: '8080',pathname: '/p/a/t/h',search: '?query=string',searchParams: URLSearchParams { 'query' => 'string' },hash: '#hash'
}
*/
console.log(myURL);

修改URL信息

const url = require('node:url');
const myURL = new URL('https://user:pass@sub.example.com:8080/p/a/t/h?query=string#hash')
myURL.port = 8081;
// https://user:pass@sub.example.com:8081/p/a/t/h?query=string#hash 8 
console.log(myURL.toString());

2. searchParams

用于读取和写入URL的query信息

const myURL = new URL('https://example.org/?abc=123');// 123console.log(myURL.searchParams.get('abc'));myURL.searchParams.append('abc', 'xyz');// https://example.org/?abc=123&abc=xyzconsole.log(myURL.href);myURL.searchParams.delete('abc');myURL.searchParams.set('a', 'b');// false
console.log(myURL.searchParams.has('abc'));// https://example.org/?a=b
console.log(myURL.href);myURL.search = new URLSearchParams('name=lily');
// https://example.org/?name=lily
console.log(myURL.href);

手动创建URLSearchParams对象

const newSearchParams = new URLSearchParams('a=b');
newSearchParams.append('a', 'c');// a=b&a=c
console.log(newSearchParams.toString());

5、querystring

querystring模块提供了一些非常实用的用于解析查询字符串的方法。

1. querystring.parse()解析查询字符串

/*{ a: 'b', c: [ 'd', 'f' ] }*/const querystring = require('node:querystring');const obj = querystring.parse('a=b&c=d&c=f');console.log(obj);

2. querystring.stringify()将对象序列化成查询字符串

const querystring = require('node:querystring'); 2const obj = {a: 'b',c: ['d', 'f']};// a=b&c=d&c=fconsole.log(querystring.stringify(obj));// a:b;c:d;c:fconsole.log(querystring.stringify(obj, ';', ':'));

6、Path模块

Path模块提供了用于处理文件和目录路径的实用程序。

1. path.basename(path, suffix)返回路径的最后一部分。

const path = require('node:path'); 2// index.htmlpath.basename('/foo/bar/baz/asdf/index.html');// indexpath.basename('/foo/bar/baz/asdf/index.html', '.html')

2. path.delimiter 返回特定平台的路径之间的分隔符。Windows使用的是‘;’,POSIX使用的是‘;’

const path = require('node:path'); 
console.log(path.delimiter);
console.log(process.env.PATH);

3. path.dirname(path)返回的是路径的目录名

const path = require('node:path'); 2
3 // /foo/bar/baz/asdf
4 path.dirname('/foo/bar/baz/asdf/quux');

4. path.extname(path)返回路径扩展名

根据最后一个 . 字符到路径结尾的字符串

const path = require('node:path');
// .html
path.extname('index.html');
// .
path.extname('index.');
//
path.extname('index');
// .md
path.extname('.index.md');

5. path.isAbsoute(path)判断是否是绝对路径

如果path是绝对路径,则返回true

const path = require('node:path');
ath.isAbsolute('/foo/bar'); // true

6. path.join([…paths])连接给定路径并format

const path = require('node:path'); 2// /foo/bar/baz/asdf
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');

7. path.normalize(path) 规范化给定路径

const path = require('node:path');
// /foo/bar/baz/asdf
path.normalize('/foo/bar//baz/asdf/quux/..');

8. path.relative(from, to) 从a到b的相对路径

根据当前工作目录返回从from到to的相对路径

const path = require('node:path'); 2
// ../../impl/bbb
path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb');

9. path.resolve([…paths])将一些路径解析成绝对路径

const path = require('node:path'); 2
// /foo/bar/baz
path.resolve('/foo/bar', './baz');

10. path.sep返回特定平台的路径中目录之间分隔符

const path = require('node:path');
// windows使用的是\,POSIX使用的是/
console.log(path.sep);

7、File模块

1. 创建文件夹mkdirSync

const { mkdirSync } = require('node:fs');
try {mkdirSync('./temp');
// 不可以同时创建不存在的多层级目录 mkdirSync('./logs/errorlog');
} catch (err) {// handle the errorconsole.log(err);
}

2. 写入文件writeFileSync(如果文件不存在,则创建文件)

const { writeFileSync } = require('node:fs');
const path = require('node:path');
try {writeFileSync(path.resolve(__dirname, './music.txt'), '新的内容', 'utf8'))
} catch (err) {// handle the error
}

3. 追加文件内容appendFileSync

const { appendFileSync } = require('node:fs');
const path = require('node:path');
try {appendFileSync(path.resolve(__dirname, './music.txt'), '新的内容88888', 'utf8'))
} catch (err) {// handle the error
}

4. 读取文件夹readdirSync

const { readdirSync } = require('node:fs');
try {const files = readdirSync('.');console.log(files);
} catch (err) {// handle the errorconsole.log(err);

5. 读取文件readFileSync

const { readFileSync } = require('node:fs');
const path = require('node:path');
try {const tent = readFileSync(path.resolve(__dirname, './music.txt'), '新的内容88888', 'utf8'))console.log(tent)
} catch (err) {// handle the error
}

6. statSync区分文件夹还是文件、判断文件或者文件夹是否存在

const { statSync } = require('node:fs');
try {const stat = statSync('./temp');if (stat.isDirectory()) {console.log('这是一个文件夹'); } else if (stat.isFile()) {console.log('这是一个文件');
} catch (err) {// handle the error
console.log(err && '文件不存在');
}

7. renameSync重命名文件


const { renameSync } = require('node:fs');
try {renameSync('./music.txt', './new-music.txt');
} catch (err) {// handle the error
}

8. rmdirSync删除文件夹

const { rmdirSync } = require('node:fs');
try {
// 目录不为空,则删除失败 rmdirSync('./temp');
} catch (err) {
// handle the errorconsole.log(err);
}

9. unlinkSync删除文件

const { unlinkSync } = require('node:fs');
try {unlinkSync('./temp');
} catch (err) {
// handle the errorconsole.log(err);
}

10. 实战:递归创建文件夹

const {mkdirSync, statSync } = require('node:fs');
const path = require('node:path');
function mkdirs(dir){const dirs = dir.split(path.sep);dirs.forEach((current, index)=>{const dirPath = dirs.slice(0, index + 1).join(path.sep);if(current){let isExisted = false;try {isExisted = statSync(dirPath).isDirectory();} catch (err) {// 说明文件不存在}if (!isExisted) {mkdirSync(dirPath)}}})
}
mkdirs(path.resolve(__dirname, './temp/logs'));

8、process模块

process 对象提供有关当前 Node.js 进程的信息。

1. cwd()返回进程的当前工作目录

const { cwd } = require('node:process'); 
// /xxxx/Node核心模块使用/10.process
console.log(cwd());

2. chdir()更改当前工作目录

const { chdir, cwd } = require('node:process');
// Starting directory: /xxxx/Node核心模块使用/10.process
console.log(`Starting directory: ${cwd()}`);
try {chdir('../');
// New directory: /xxxx/Node核心模块使用console.log(`New directory: ${cwd()}`);
} catch (err) {console.error(`chdir: ${err}`);
}

3. process.env 环境变量

const process = require('node:process');
console.log(process.env);process.env.mode = 'development';
console.log(process.env);

9、Events模块

Node.js的大部分核心API都是围绕着一种异步事件驱动架构构建的。在这种架构中,某些类型的对象(称为“ emitters ”)会发出特定的具名事件,因此导致调用Function对象(“listeners”)

1. on/emit基本用法

const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();myEmitter.on('event', () => {
console.log('an event occurred!');
});myEmitter.emit('event');

2. 传递参数和 listener中的this

const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();myEmitter.on('event', function (a, b) {
// a, b, true
console.log(a, b, this === myEmitter);
});myEmitter.emit('event', 'a', 'b');

3. 只触发一次的事件函数

const EventEmitter = require('node:events'); 
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
letm=0;
myEmitter.once('event', () => {console.log(++m);
});
// 1
myEmitter.emit('event'); 
// 没有反应 
myEmitter.emit('event');

4. 绑定多个listeners

eventEmitter.listeners返回函数列表。

const EventEmitter = require('node:events');
const myEmitter = new EventEmitter();myEmitter.on('event', function firstListener() {console.log('Helloooo! first listener');
});myEmitter.on('event', function secondListener(arg1, arg2) {console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});myEmitter.on('event', function thirdListener(...args) {const parameters = args.join(', ');console.log(`event with parameters ${parameters} in third listener`);
});console.log(myEmitter.listeners('event'));myEmitter.emit('event', 1, 2, 3, 4, 5);

5. 返回所有的事件名称

eventEmitter.eventNames返回所有的事件名称列表。

onst EventEmitter = require('node:events');const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});// ['foo', 'bar']
console.log(myEE.eventNames());

6. 移除listener

eventEmitter.off是eventEmitter.removeListener 的别名。

const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();const callbackA = () => {console.log('A');myEmitter.removeListener('event', callbackB);
};const callbackB = () => {console.log('B');
};myEmitter.on('event', callbackA);myEmitter.on('event', callbackB);// A、B
myEmitter.emit('event');// A
myEmitter.emit('event');

7. 移除所有的listener

eventEmitter.removeAllListeners 移除指定的事件所有绑定过的回调函数。

const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();const callbackA = () => {console.log('A');
};const callbackB = () => {console.log('B');
};myEmitter.on('event', callbackA);myEmitter.on('event', callbackB);// A、B
myEmitter.emit('event');myEmitter.removeAllListeners('event');// 没有反应
myEmitter.emit('event');

10、Stream模块

Stream是一个抽象接口,用于处理Node.js中的流数据。node:stream模块为实现流接口提供了API。
Stream可以是可读的,也可以是可写的,或者两者都有。所有流都是EventEmitter的实例。
Node.js提供了很多流对象,比如操作文件系统、对HTTP服务的请求等。
通常在处理大体积文件的时候用到流,防止占用过多的内存。

1. 创建文件只读流

// 创建只读流
const { createReadStream, statSync } = require('node:fs');// highWaterMark
const stream = createReadStream('./demo.txt', { encoding: 'utf8' });let totalLength = 0;
stream.on('data', (chunk) => {totalLength += Buffer.byteLength(chunk);
});stream.on('end', () => {console.log(`数据读取完毕`);console.log(statSync('./demo.txt').size);console.log(totalLength);
});

2. 创建文件可写流

// 复制文件
const { createReadStream, createWriteStream, statSync } = require('node:fs');const readStream = createReadStream('./demo.txt', { encoding: 'utf8' });
const writeStream = createWriteStream('./demo-write.txt', { encoding: 'utf8' });// 方式1:手动写入
readStream.on('data', (chunk) => {writeStream.write(chunk);
});readStream.on('end', () => {console.log(`数据写入完毕`);console.log(statSync('./demo.txt').size === statSync('./demo-write.txt').size);
});// 方式2:通过管道完成写入
readStream.on('end', () => {console.log(`数据读取完毕`);}).pipe(writeStream).on('finish', () => {console.log(`写入完毕`);console.log(statSync('./demo.txt').size === statSync('./demo-write.txt').size);})

3. 转换流

// 压缩文件
const { createReadStream, createWriteStream } = require('node:fs');
const zlib = require('node:zlib');const readStream = createReadStream('./demo.txt');
const duplexStream = zlib.createGzip();
const writeStream = createWriteStream('./demo.tar.gz');readStream.pipe(duplexStream).pipe(writeStream);

4. 下载文件

const { createReadStream } = require('node:fs');
const zlib = require('node:zlib');
const http = require('node:http');http.createServer((req, res) => {res.writeHead(200, {'Content-Type': 'application/octet-stream','Content-Encoding': 'gzip','Content-Disposition': 'attachment; filename=demo.tar.gz',});const readStream = createReadStream('./demo.txt');const duplexStream = zlib.createGzip();readStream.pipe(duplexStream).pipe(res);
}).listen(8890);

5. readline模块

node:readline模块提供了一个接口,用于一次一行地从Readable流读取数据。

const readline = require('node:readline');
const { stdin: input, stdout: output } = require('node:process');const rl = readline.createInterface({ input, output });rl.question('What do you think of Node.js? ', (answer) => {console.log(answer);rl.close();
});

逐行读取文件内容


const { createInterface } = require('node:readline');
const { once } = require('node:events');
const { createReadStream } = require('node:fs');(async () => {const rl = createInterface({input: createReadStream('./demo.txt'),});let line = 0;rl.on('line', (lineContent) => {console.log(`${++line}:`, lineContent.toString());});await once(rl, 'close');console.log('File read complete.');
})();

11、 HTTP模块

http模块是一个非常常用的模块,我们可以用它来搭建一个服务器,或者使用它发送请求。

1. 搭建服务器

const http = require('node:http');
const { Buffer } = require('node:buffer');
const { URL } = require('node:url');
const querystring = require('node:querystring');// 程序支持的HTTP方法列表
// console.log(http.METHODS);// 所有标准HTTP响应状态代码的集合,以及每个状态代码的简短描述。
// console.log(http.STATUS_CODES);const server = http.createServer((req, res) => {/* ---------  Request   ---------- */// console.log(req.headers);// console.log(req.headers['cookie']);// console.log(req.httpVersion);// console.log(req.method);// console.log(req.url);// GET请求// console.log('query:', new URL(req.url, 'http://localhost:8888').searchParams);/* ---------  Response   ---------- */// 状态码和状态码描述// 获取状态码// console.log(res.statusCode);// console.log(res.statusMessage);// 设置状态码// res.statusCode = 404;// res.statusMessage = 'not found';// 设置响应头信息res.setHeader('Content-Type', 'text/html');res.setHeader('X-Foo', 'Bar');// res.writeHead(status, statusMessage, headers)// res.writeHead(200, 'Very OK', { 'Content-Type': 'text/plain' });// 获取响应头信息(header name自动转换成小写)// console.log(res.getHeaders());// console.log(res.getHeaderNames());// console.log(res.getHeader('X-Foo'));// console.log(res.hasHeader('X-Foo'));// 响应主体信息// res.write(chunk: string | buffer, encoding, callback)res.write(Buffer.from('hello world'))res.write('ok 1');res.write('ok 2');// res.end(data, encoding, callback); 相当于 res.write(data, encoding) + res.end(callback)res.end('ok end', 'utf8', () => {console.log('数据发送完成');});
});// 启动服务
server.listen(8888, 'localhost', () => {console.log('服务启动成功');
});// 关闭服务
// server.on('close', () => {
//     console.log('The server is closed');
// });// server.close(() => {
//     console.log('Close the server.');
// });

2. 获取POST请求的数据

const http = require('node:http');
const querystring = require('node:querystring');const server = http.createServer((req, res) => {if (req.method === 'POST') {let postData = '';req.on('data', (chunk) => {postData += chunk.toString();});req.on('end', () => {console.log('postData:', querystring.parse(postData));res.end('POST request end');});} else {res.end('Other request end');}
});server.listen(8888, 'localhost', () => {console.log('服务启动成功');
});

3. 客户端:发送GET网络请求

// http-server.js
const http = require('node:http');const server = http.createServer((req, res) => {if (req.method === 'GET') {console.log(req.headers['x-auth']);res.setHeader('Content-Type', 'text/html');res.end('This is a get request');} else if (req.method === 'POST') {// 接收client发送过来的数据let postData = '';req.on('data', (chunk) => {postData += chunk.toString();});req.on('end', () => {console.log('postData:', postData);res.setHeader('Content-Type', 'application/json');res.end(JSON.stringify({ a: 'b' }));});} else {res.statusCode = 404;res.end();}
});server.listen(8889, 'localhost', () => {console.log('服务启动成功');
});// 关闭服务
server.on('error', (error) => {console.log('The server has error', error.message);
})server.on('close', () => {console.log('The server is closed');
});
// http-get.js
const http = require('node:http');// http.get(url, options, callback)
const client = http.get('http://localhost:8889/?a=b', {headers: {'X-AUTH': '1234',},
}, (res) => {console.log(res.statusCode);console.log(res.headers);res.setEncoding('utf8');// 获取返回的内容let rawData = '';res.on('data', (chunk) => {rawData += chunk;});res.on('end', () => {console.log('data:', rawData);});
});// 请求服务出现错误
client.on('error', (e) => {console.log('client error info', e.message);
});// 关闭客户端
client.end();

4. 客户端:发送POST网络请求

// http-post.js
const http = require('node:http');
const { Buffer } = require('node:buffer');const postData = JSON.stringify({'msg': 'Hello World!',
});// http.request(options, callback)
const client = http.request({protocol: 'http:',hostname: 'localhost',port: '8889',pathname: '/',method: 'POST',headers: {'Content-Type': 'application/json','Content-Length': Buffer.byteLength(postData),},}, (res) => {console.log(res.statusCode);console.log(res.headers);res.setEncoding('utf8');// 获取返回的内容let rawData = '';res.on('data', (chunk) => {rawData += chunk;});res.on('end', () => {console.log('data:', rawData);});
});// 请求服务出现错误
client.on('error', (e) => {console.log('client error info', e.message);
});client.write(postData);// 关闭客户端
client.end();

http://www.mrgr.cn/news/5804.html

相关文章:

  • 每日一问:为什么MySQL索引使用B+树? 第4版 (含时间复杂度对比表格)
  • 一NULL为甚?
  • Redis管道
  • 提升代码可读性的十八条建议2
  • LNMP学习
  • C学习(数据结构)--> 实现顺序结构二叉树
  • 在亚马逊云科技上提取视频内容并利用AI大模型开发视频内容问答服务
  • 海山数据库(He3DB)源码详解:CommitTransaction函数源码详解
  • Shell编程之条件语句
  • 开发者空间实践指导:基于华为云3大PaaS主流服务轻松实现文字转换语音
  • 【C++】STL简介
  • 社区流浪动物救助系统-计算机毕设Java|springboot实战项目
  • 探索TensorFlow:深度学习的未来
  • 手把手教你手写单例,六种实现方式一网打尽!
  • fpga图像处理实战-对数变换
  • Mybatis的分页,延迟加载和缓存
  • docker具体操作
  • Qt实现圆型控件的三种方法之子类化控件并重写paintEvent
  • webpack打包html
  • 使用docker-compose运行kafka及验证(无需zookpeer)