【Nodejs】nodejs内置模块(中)

在这里插入图片描述

1.路劲处理模块 path


1.1 模块概览

在nodejs中,path是个使用频率很高,但却让人又爱又恨的模块。部分因为文档说的不够清晰,部分因为接口的平台差异性。将path的接口按照用途归类,仔细琢磨琢磨,也就没那么费解了。

1.2 获取路径/文件名/扩展名

  • 获取路径:path.dirname(filepath)
  • 获取文件名:path.basename(filepath)
  • 获取扩展名:path.extname(filepath)

(1)获取所在路径
例子如下:

var path = require('path');
var filepath = '/tmp/demo/js/test.js';

// 输出:/tmp/demo/js
console.log( path.dirname(filepath) );

(2)获取文件名
严格意义上来说,path.basename(filepath) 只是输出路径的最后一部分,并不会判断是否文件名。但大部分时候,我们可以用它来作为简易的“获取文件名“的方法。

var path = require('path');

// 输出:test.js
console.log( path.basename('/tmp/demo/js/test.js') );

// 输出:test
console.log( path.basename('/tmp/demo/js/test/') );

// 输出:test
console.log( path.basename('/tmp/demo/js/test') );

如果只想获取文件名,单不包括文件扩展呢?可以用上第二个参数。

// 输出:test
console.log( path.basename('/tmp/demo/js/test.js', '.js') );

(3) 获取文件扩展名
简单的例子如下:

var path = require('path');
var filepath = '/tmp/demo/js/test.js';

// 输出:.js
console.log( path.extname(filepath) );

更详细的规则是如下:(假设 path.basename(filepath) === B )

  • 从B的最后一个.开始截取,直到最后一个字符。
  • 如果B中不存在.,或者B的第一个字符就是.,那么返回空字符串。

直接看官方文档的例子

path.extname('index.html')
// returns '.html'

path.extname('index.coffee.md')
// returns '.md'

path.extname('index.')
// returns '.'

path.extname('index')
// returns ''

path.extname('.index')
// returns ''

1.3 路径组合

path.join([...paths])
path.resolve([...paths])

(1) path.resolve() 生成完成的绝对路径
语法格式:

path.resolve([...myPaths])

解释:

  • 将路径或路径片段的序列解析为绝对路径。
  • 返回的路径是从右往左处理,后面的每个 myPath 被依次解析,直到构造出一个完整的绝对路径。

你可以想象现在你在shell下面,从左到右运行一遍cd path命令,最终获取的绝对路径/文件名,就是这个接口所返回的结果了。
代码举例:

const path = require('path');

let arr1 = ['/foo1/foo2', 'dselegent', 'foo3'];
let result1 = path.resolve(...arr1);
console.log(result1); // 打印结果:/foo1/foo2/dselegent/foo3

let arr2 = ['/foo1/foo2', '/dselegent', 'foo3'];
let result2 = path.resolve(...arr2);
console.log(result2); // 打印结果:/dselegent/foo3
const path = require('path');

// 假设当前工作路径是 /Users/a/Documents/git-code/nodejs-learning-guide/examples/2016.11.08-node-path

// 输出 /Users/a/Documents/git-code/nodejs-learning-guide/examples/2016.11.08-node-path
console.log( path.resolve('') )

// 输出 /Users/a/Documents/git-code/nodejs-learning-guide/examples/2016.11.08-node-path
console.log( path.resolve('.') )

// 输出 /foo/bar/baz
console.log( path.resolve('/foo/bar', './baz') );

// 输出 /foo/bar/baz
console.log( path.resolve('/foo/bar', './baz/') );

// 输出 /tmp/file
console.log( path.resolve('/foo/bar', '/tmp/file/') );

// 输出 /Users/a/Documents/git-code/nodejs-learning-guide/examples/2016.11.08-node-path/www/js/mod.js
console.log( path.resolve('www', 'js/upload', '../mod.js') );

(2) path.join() 将多个路径进行拼接
如果是我们手动拼接路径,容易出错。这个时候,可以利用 path.join() 方法将路径进行拼接。

语法格式:

path.join([...paths]);

解释:使用平台特定的分隔符作为定界符将所有给定的 path 片段连接在一起,然后规范化生成的路径。

代码举例:

const path = require('path');

const result1 = path.join(__dirname, './app.js');
console.log(result1); // 返回:/Users/smyhvae/dselegent/app.js

const result2 = path.join('/foo1', 'foo2', './foo3');
console.log(result2); // 返回:/foo1/foo2/foo3

const result3 = path.join('/foo1', 'foo2', '/foo3');
console.log(result3); // 返回:/foo1/foo2/foo3

(3) path.resolvepath.join 区别
path.resolvepath.join 都是属于 path 核心模块下的方法,用来拼接路径。

都可以拼接成一个完整路径.

const path = require("path");

var dirname = '/User/Desktop';
var basename = 'abc.txt';

path.join(dirname, basename);  // /User/Desktop/abc.txt

path.resolve(dirname, basename);  // /User/Desktop/abc.txt

如果 dirname 是以 ./ 、…/、不加 / 开头的话,那么 resolve 会找到磁盘下的根目录

const path = require("path");
 
var dirname = '../User/Desktop';
var basename = 'abc.txt';
 
path.join(dirname, basename);  // ../User/Desktop/abc.txt
 
path.resolve(dirname, basename);  // /Users/Desktop/node/User/Desktop/abc.txt

如果 basename 是以 / 开头的,那么 resolve 就会直接返回 basename

const path = require("path");
 
var dirname = '/User/Desktop';
var basename = '/abc.txt';
 
path.join(dirname, basename);  // /User/Desktop/abc.txt
 
path.resolve(dirname, basename);  // /abc.txt

1.4 几个常见路径

__dirname:这是一个常量,表示:当前执行文件所在完整目录。
__filename:这是一个常量。表示:当前执行文件的完整目录 + 文件名。
process.cwd:获取当前执行 Node命令 时的目录名。
代码举例:

console.log(__dirname);
console.log(__filename);
console.log(process.cwd());

运行结果:

$ node app.js

/Users/smyhvae/dselegent
/Users/smyhvae/dselegent/app.js
/Users/smyhvae/dselegent

2.本地文件操作模块 fs


Node.js 中的同步和异步的区别
fs模块对文件的几乎所有操作都有同步和异步两种形式。例如:readFile()readFileSync()

区别:

  • 同步调用会阻塞代码的执行,异步则不会。
  • 异步调用会将 读取任务 下达到任务队列,直到任务执行完成才会回调。
  • 异常处理方面:同步必须使用 try catch 方式,异步可以通过回调函数的第一个参数。【★★★★★

2.1 文件读取

同步读取

var fs = require('fs');
var data;

try{
    data = fs.readFileSync('./fileForRead.txt', 'utf8');
    console.log('文件内容: ' + data);
}catch(err){
    console.error('读取文件出错: ' + err.message);
}

输出如下:

/usr/local/bin/node readFileSync.js
文件内容: hello world

异步读取

var fs = require('fs');

fs.readFile('./fileForRead.txt', 'utf8', function(err, data){
    if(err){
        return console.error('读取文件出错: ' + err.message);
    }
    console.log('文件内容: ' + data);
});

输出如下

/usr/local/bin/node readFile.js
文件内容: hello world

fs/promises 从 Node.js 14 开始可用 从 Node.js 14 开始,fs 模块提供了两种使用基于 promises 的文件系统的方法。这些 promises 可以通过 require('fs').promises 或 require('fs/promises') 获得。

import { readFile } from 'fs/promises';

try {
  const contents = await readFile(filePath, { encoding: 'utf8' });
  console.log(contents);
} catch (err) {
  console.error(err.message);
}

2.2 文件写入

备注:以下代码,如果文件不存在,则创建文件;如果文件存在,则覆盖文件内容;

异步写入

var fs = require('fs');

fs.writeFile('./fileForWrite.txt', 'hello world', 'utf8', function(err){
    if(err) throw err;
    console.log('文件写入成功');
});

同步写入

var fs = require('fs');

try{
    fs.writeFileSync('./fileForWrite1.txt', 'hello world', 'utf8');
    console.log('文件写入成功');
}catch(err){
    throw err;
}

promises

import { writeFile } from 'fs/promises';

try {
  const contents = await writeFile('message.txt', 'hello world', { encoding: 'utf8' });
  console.log(contents);
} catch (err) {
  // When a request is aborted - err is an AbortError
  console.error(err);
}

2.3 文件是否存在

fs.exists()已经是deprecated状态,现在可以通过下面代码判断文件是否存在。

异步本

const fs = require('fs')

//检查文件是否存在于当前目录中
fs.access('package.json', fs.constants.F_OK, err => {
    if(err) {
        console.log('package.json不存在于当前目录中')
        return
    }
    console.log('package.json存在于当前目录中')
})

fs.access('index.js', fs.constants.F_OK, err => {
    if(err) {
        console.log('index.js不存在于当前目录中')
        return
    }
    console.log('index.js存在于当前目录中')
})

fs.access()除了判断文件是否存在(默认模式),还可以用来判断文件的权限。

备忘:fs.constants.F_OK等常量无法获取(node v6.1,mac 10.11.4下,fs.constantsundefined

同步

import { accessSync, constants } from 'fs';

try {
  accessSync('etc/passwd', constants.R_OK );
  console.log('can read');
} catch (err) {
  console.error('no access!');
}

promises

import { access, constants } from 'node:fs/promises';

try {
  await access('/etc/passwd', constants.R_OK);
  console.log('can access');
} catch {
  console.error('cannot access');
}

2.4 删除文件

异步版本

var fs = require('fs');

fs.unlink('./fileForUnlink.txt', function(err){
    if(err) throw err;
    console.log('文件删除成功');
});

同步版本

import { unlinkSync } from 'fs';

try {
  unlinkSync('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (err) {
  // handle the error
}

promises

import { unlink } from 'fs/promises';

try {
  await unlink('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (err) {
  // handle the error
}

2.5 创建目录

异步版本(如果目录已存在,会报错)

// fs.mkdir(path[, mode], callback)
var fs = require('fs');

fs.mkdir('sub', function(err){
    if(err) throw err;
    console.log('创建目录成功');
});

同步版本

// fs.mkdirSync(path[, mode])
var fs = require('fs');

try{
    fs.mkdirSync('hello');
    console.log('创建目录成功');
}catch(e){
    throw e;
}

promises

import { mkdir } from 'fs/promises';

try {
  const createDir = await mkdir(projectFolder, { recursive: true });
  console.log(`created ${createDir}`);
} catch (err) {
  console.error(err.message);
}

2.6 遍历目录

同步版本,注意:fs.readdirSync()只会读一层,所以需要判断文件类型是否目录,如果是,则进行递归遍历。

// fs.readdirSync(path[, options])
var fs = require('fs');
var path = require('path');
var getFilesInDir = function(dir){
    var results = [ path.resolve(dir) ];
    var files = fs.readdirSync(dir, 'utf8');
    files.forEach(function(file){
        file = path.resolve(dir, file);
        var stats = fs.statSync(file);
        if(stats.isFile()){
            results.push(file);
        }else if(stats.isDirectory()){
            results = results.concat( getFilesInDir(file) );
        }
    });
    return results;
};
var files = getFilesInDir('../');
console.log(files);

2.7 读取目录

import { readdir } from 'fs/promises';

try {
  const files = await readdir(path);
  for (const file of files)
    console.log(file);
} catch (err) {
  console.error(err);
}

2.8 删除目录

// 删除目录(前提没有文件在里面)
fs.rmdir('./avatar', err => {
  if (err && err.code === 'ENOENT') {
    console.log('目录不存在');
  }
});

2.9 删除整个目录

//1
const fs = require("fs")
fs.("./avatar",(err,data)=>{
    // console.log(data)
    data.forEach(item=>{
        fs.unlinkSync(`./avatar/${item}`)
    })

    fs.rmdir("./avatar",(err)=>{
        console.log(err)
    })
})

//2
const fs = require('fs')
fs.readdir("./avatar").then(async (data)=>{
    let arr = []
    data.forEach(item=>{
        arr.push(fs.unlink(`./avatar/${item}`))
    })
    await Promise.all(arr)
    fs.rmdir("./avatar")
})

//3
const fs = require('fs').promises;
fs.readdir('./image2').then(async data => {
  await Promise.all(data.map(item => fs.unlink(`./image2/${item}`)));
  await fs.rmdir('./image2');
});

2.10 文件重命名

异步版本

// fs.rename(oldPath, newPath, callback)
var fs = require('fs');

fs.rename('./hello', './world', function(err){
    if(err) throw err;
    console.log('重命名成功');
});

同步版本

// fs.renameSync(oldPath, newPath)
var fs = require('fs');

fs.renameSync('./world', './hello');
promises

import { rename } from 'fs/promises';

try {
  await rename('./world', './hello');
  console.log(`rename`);
} catch (err) {
  console.error(err.message);
}

2.11 获取文件状态

(1)异步:fs.stat(path,callback): path是一个表示路径的字符串,callback接收两个参数(err,stats),其中stats就是fs.stats的一个实例;

(2)同步:fs.statSync(path) 只接收一个path变量,fs.statSync(path)其实是一个fs.stats的一个实例;

方法

  • stats.isFile() – 是否文件
  • stats.isDirectory() – 是否目录
// Node.js program to demonstrate the 
// fs.statSync() method 
  
// Import the filesystem module 
const fs = require('fs'); 
  
// Getting information for a file 
statsObj = fs.statSync("test_file.txt"); 
  
console.log(statsObj);  
console.log("Path is file:", statsObj.isFile()); 
console.log("Path is directory:", statsObj.isDirectory()); 
  
// Getting information for a directory 
statsObj = fs.statSync("test_directory"); 
  
console.log(statsObj); 
console.log("Path is file:", statsObj.isFile()); 
console.log("Path is directory:", statsObj.isDirectory());

输出:

Stats {
  dev:3229478529,
  mode:33206,
  nlink:1,
  uid:0,
  gid:0,
  rdev:0,
  blksize:4096,
  ino:1970324837039946,
  size:0,
  blocks:0,
  atimeMs:1582306776282,
  mtimeMs:1582482953967,
  ctimeMs:1582482953968.2532,
  birthtimeMs:1582306776282.142,
  atime:2020-02-21T17:39:36.282Z,
  mtime:2020-02-23T18:35:53.967Z,
  ctime:2020-02-23T18:35:53.968Z,
  birthtime:2020-02-21T17:39:36.282Z
}
Path is file:true
Path is directory:false
Stats {
  dev:3229478529,
  mode:16822,
  nlink:1,
  uid:0,
  gid:0,
  rdev:0,
  blksize:4096,
  ino:562949953486669,
  size:0,
  blocks:0,
  atimeMs:1582482965037.8445,
  mtimeMs:1581074249467.7114,
  ctimeMs:1582482964979.8303,
  birthtimeMs:1582306776288.1958,
  atime:2020-02-23T18:36:05.038Z,
  mtime:2020-02-07T11:17:29.468Z,
  ctime:2020-02-23T18:36:04.980Z,
  birthtime:2020-02-21T17:39:36.288Z
}
Path is file:false
Path is directory:true

2.12 追加文件内容

fs.appendFile(file, data[, options], callback)

  • file:可以是文件路径,也可以是文件句柄。(还可以是buffer?)
  • data:要追加的内容。string或者buffer。
  • options
    • encoding:编码,默认是utf8
    • mode:默认是0o666
  • flag:默认是a

注意:如果file是文件句柄,那么

  • 开始追加数据前,file需要已经打开。
  • file需要手动关闭。
var fs = require('fs');
fs.appendFile('./extra/fileForAppend.txt', 'hello', 'utf8', function(err){
    if(err) throw err;
    console.log('append成功');
});

3.事件机制模块 events


Node.js 有多个内置的事件,我们可以通过引入events模块,并通过实例化EventEmitter类来绑定和监听事件,如下实例:

// 引入 events 模块
var EventEmitter = require('events');
// 创建 eventEmitter 对象
var event = new EventEmitter();

以下程序绑定事件处理程序:

// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);

我们可以通过程序触发事件:

// 触发事件
eventEmitter.emit('eventName');

EventEmitter的每个事件由一个事件名和若干个参数组成,事件名是一个字符串,通常表达一定的语义。对于每个事件,EventEmitter 支持 若干个事件监听器。

当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。

让我们以下面的例子解释这个过程:

// 引入 events 模块
var EventEmitter = require('events');
// 创建 eventEmitter 对象
var event = new EventEmitter();
event.on('someEvent', function(arg1, arg2) { 
    console.log('listener1', arg1, arg2); 
}); 
event.on('someEvent', function(arg1, arg2) { 
    console.log('listener2', arg1, arg2); 
}); 
event.emit('someEvent', 'arg1 参数', 'arg2 参数'); 

执行以上代码,运行的结果如下:

$ node event.js 
listener1 arg1 参数 arg2 参数
listener2 arg1 参数 arg2 参数

以上例子中,event为事件someEvent注册了两个事件监听器,然后触发了 someEvent 事件。

运行结果中可以看到两个事件监听器回调函数被先后调用。 这就是EventEmitter最简单的用法。

EventEmitter提供了多个属性,如onemiton函数用于绑定事件函数,emit属性用于触发一个事件

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python基于PyTorch实现卷积神经网络分类模型(CNN分类算法)项目实战

说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 卷积神经网络,简称为卷积网络,与普通神经网络的区别是它的卷积层内的神经元只覆…

FUNBOX_1靶场详解

FUNBOX_1靶场复盘 这个系列的靶场给出的干扰因素都挺多的,必须从中找到有用的线索才可以。 这个靶场你扫描到ip地址后打开网页会发现,ip自动转换成域名了,所以我们需要添加一条hosts解析才可以。 192.168.102.190 funbox.fritz.box从目录…

vue中预览静态pdf文件

方法 // pdf预览 viewFileCompare() { const pdfUrl "/static/wjbd.pdf"; window.open(pdfUrl); }, // 下载 downloadFile(){ var a document.createElement("a"); a.href "/static/wjbd.pdf"; a.…

自学网络安全(黑客),遇到问题怎么解决

自学网络安全很容易学着学着就迷茫了,找到源头问题,解决它就可以了,所以首先咱们聊聊,学习网络安全方向通常会有哪些问题,看到后面有惊喜哦 1、打基础时间太长 学基础花费很长时间,光语言都有几门&#xf…

专项练习-1数据结构-02字符串

1. 下面关于「串」的叙述中,哪一个是不正确的?( ) A 串是字符的有限序列 B 空串是由空格构成的串 C 模式匹配是串的一种重要运算 D 串既可以采用顺序存储,也可以采用链式存储 正确答案:B 官方解析&…

如何在3ds max中创建可用于真人场景的巨型机器人:第 1部分

推荐: NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 创建主体 步骤 1 打开 3ds Max。 打开 3ds Max 步骤 2 在左侧视口中,按键盘上的 Alt-B 键。它 打开视口配置窗口。 打开“锁定缩放/平移”和“匹配位图”选项。单击“文件”并转到参考 …

实验二十四、滞回比较器电压传输特性的测量

一、题目 滞回比较器电压传输特性的测量。 二、仿真电路 电路如图1所示。 为便于观察电压传输特性的变化,输入信号采用信号发生器产生的幅值为 10 V 10\,\textrm V 10V、频率为 20 Hz 20\,\textrm{Hz} 20Hz 的三角波电压。采用虚拟的运算放大电路,其…

从娱乐产品到效率工具,ARknovv首款AR眼镜回归“AR本质”

如果说2022年是AR的元年,2023年则有望成为消费级AR眼镜的新拐点。 今年AR眼镜行业发展明显加快,且不断有大厂入局:今年2月小米发布无线AR眼镜探索版;3月荣耀也推出了一款全新的观影眼镜;而苹果在6月发布的MR头显Visio…

[面试官,你坐好],今天我给你吹下卡顿监控

这是一篇面试总结稿,根据之前的面试过程以一种模拟面试的风格进行阐述。 面试官: 自我介绍下 诶?这面试官头发还比较多,应该不牛逼,心里踏实了不少。我: 面试官你好,我叫**,5年工作经验。曾经跟OPPO产品PK&…

甄云质量管理解决方案——插上数字“羽翼”,实现PPAP落地

导语 质量管理是供应链管理中非常重要的一环,通过制定和开展质量相关的活动,确保产品符合质量标准和一致性要求。质量管理水平的高低直接影响供应链的整体效率和最终效益,关乎企业形象和品牌声誉,已然是企业的生命线。 作为采购…

ES6:Object.assign方法详解

ES6:Object.assign方法详解 1、前言2、语法3、基本用法3.1 目标对象和源对象无重名属性3.2 目标对象和源对象有重名属性3.3 有多个源对象3.4 其他情况3.4.1 只有一个参数时,Object.assign会直接返回该参数3.4.2 如果该参数不是对象,则会先转成…

el-table 表头设置渐变色

<el-table :data"tableData" stripe><el-table-column prop"name" label"测试" align"left"></el-table-column><el-table-column prop"code" label"测试1" align"left"></…

科技云报道:边缘云赛道开启,谁能成为首个“出线”厂商?

科技云报道原创。 每一轮底层技术变革&#xff0c;都会带来全新的商业机遇。随着万物智联时代到来&#xff0c;大量数据产生的源头由传统的中心化向分散数据源变革&#xff0c;越来越多云边协同场景的出现&#xff0c;使得边缘云成为计算领域数据处理的新范式之一。 自2020年…

OR-Tools工具安装(Python-Vs code)-自用

安装&#xff08;已安装python以及Vs code&#xff09; pip安装 python -m pip install --user ortools安装完成示意如下&#xff1a; 验证安装 python -c "import ortools; print(ortools.__version__)"输出结果为版本号

网络:TCP/IP协议

1. OSI七层参考模型 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 2. TCP/IP模型 应用层 传输层 网络层 数据链路层 物理层 3. 各链路层对应的名称 应用层对应的是协议数据单元 传输层对应的是数据段 网络层对应的是数据包 链路层对应的是数据帧 物理层对应的是比特…

Mysql 简介

Mysql 简介 学习目的 MySQL作为目前最流行的关系型数据库管理系统之一&#xff0c;因其开源免费的特性&#xff0c;成为小型Web应用的重点关注对象。几乎所有的动态Web应用基本都在使用MySQL作为数据管理系统。学习MySQL的目的也是为了更好地理解数据库相关的SQL注入漏洞&…

uniapp实战

上面是tab栏&#xff0c;下面是swiper&#xff0c;&#xff0c;tab和swiper和 红色滑块 动态变化&#xff0c;&#xff0c; 遇到的问题&#xff1a; 往下滚动 tab栏 吸顶&#xff1a; position:sticky; z-index:99; top:0;swiper切换触发 change 事件&#xff0c; :current …

【Unity2D】相机移动以及设置相机边界

添加相机 添加相机时&#xff0c;首先需要在unity中添加 Cinemachine 包 第一次使用这个包时&#xff0c;需要在Package Manager中搜索并安装 安装Camera Mechine包后&#xff0c;添加2D Camera 设置跟随对象为Ruby &#xff08;从Hierarchy中将Ruby拖动到Follow中&#xff0…

UE5 关于MRQ渲染器参数

最佳参数&#xff1a; Spatial Sample Count&#xff1a;使用奇数样本时临时抗锯齿会收敛 Temporal Sample Count&#xff1a;超过2之后&#xff0c;采样过大会造成TAA效果不佳 TSR&#xff1a;UE5最好的抗锯齿方案

AcWing241. 楼兰图腾(树状数组)

输入样例&#xff1a; 5 1 5 3 2 4输出样例&#xff1a; 3 4解析&#xff1a; 以某个点 i 为最低点的 V 的数量&#xff0c;为 i 左侧和右侧比 a[ i ] 大的数量 a&#xff0c;b 的乘积。 但是&#xff0c;直接求这两个数的复杂度为O(n)&#xff0c;则整个复杂度为O( n^2 )&am…