Node入门笔记

news2024/10/9 11:24:47

一、认识NodeJS

  • Node.js是一个JavaScript运行环境。让Javascript可以开发后端程序。
  • Node.js 使用了一个事件驱动非阻塞式 I/O的模型,使其轻量又高效。
  • Node.js 的包管理工具 npm 是全球最大的开源库生态系统。
  • Node.js可以解析JS代码,提供很多系统级别的API
    • 文件的读写(File System)
    • 进程的管理(process)
    • 网络通信(Http/Https)
Node.js的应用
1、BFF中间层
  • BFF,即 Backend For Frontend(服务于前端的后端)。
  • BFF 模式下,整体分工很清晰,后端通过 Java/C++ 等语言负责服务实现,理想情况下给前端提供的是基于领域模型的 RPC 接口,前端则在 BFF 层直接调用服务端 RPC 接口拿到数据,按需加工消费数据,并实现人机交互。基于 BFF 模式的研发,很适合拥有前端技术背景的全栈型工程师。这种模式的好处很明显,后端可以专注于业务领域,更多从领域模型的视角去思考问题,页面视角的数据则交给前端型全栈工程师去搞定。领域模型与页面数据是两种思维模式,通过 BFF 可以很好地解耦开,让彼此更专业高效
  • Node.js 非常适合用来做 BFF 层,优势如下:
    • 对于前端来说:让前端有能力自由组装后台数据,这样可以减少大量的业务沟通成本,加快业务的迭代速度;并且,前端同学能够自主决定与后台的通讯方式。
    • 对于后台和运维来说,好处是:安全性(不会把主服务器暴露在外面)、降低主服务器的复杂度等。
2、服务端渲染
  • 客户端渲染(CSR / Client side render):前端通过一大堆接口请求数据,然后通过 JS 动态处理和生成页面结构和展示。优点是前后端分离、减小服务器压力、局部刷新。缺点是不利于 SEO(如果你的页面然后通过 Ajax 异步获取内容,抓取工具并不会等待异步完成后再行抓取页面内容)、首屏渲染慢。
  • 服务端渲染(SSR / Server Side Render):服务器返回的不是接口数据,而是一整个页面(或整个楼层)的 HTML 字符串,浏览器直接显示即可。也就是说,在服务器端直接就渲染好了,然后一次性打包返回给前端。优点是有利于 SEO、首屏渲染很快
  • 总结: 搜索引擎优化 + 首屏速度优化 = 服务端渲染
3、小型服务和小型网站的后端
  • 基于express、koa等框架可以实现后端服务
4、项目构建工具
  • gulp、webpack等都是基于Node.js实现的
5、PC客户端软件
  • Electron基于Node.js实现的
Node.js的特点
  • 异步、非阻塞 IO 模型
  • 事件循环
  • 单线程
  • 总结:轻量和高效
  • 这里所谓的“单线程”,指的是 Node 的主线程只有一个。为了确保主线程不被阻塞,主线程是用于接收客户端请求。但不会处理具体的任务。而 Node 的背后还有一个线程池,线程池会处理长时间运行的任务(比如 IO 操作、网络操作)。线程池里的任务是通过队列和事件循环的机制来执行。
Node.js的劣势
  • 程序运行不稳定,可能会出现服务不可用的情况
  • 程序运行效率较低,每秒的请求数维持在一个较低的水平

二、Npm & Yarn

  • 由于 Node 是一套轻内核的平台,虽然提供了一系列的内置模块,但是不足以满足开发者的需求,于是乎出现了包(package)的概念: 与核心模块类似,就是将一些预先设计好的功能或者说 API 封装到一个文件夹,提供给开发者使用
  • 包的加载机制
Node.js中使用CommonJs模块化机制,通过npm下载的第三方包,我们在项目中引入第三方包都是:let xx = require('第三方包名')

1. `require('第三方包名')`优先在加载该包的模块的同级目录`node_modules`中查找第三方包。
2. 找到该第三方包中的`package.json`文件,并且找到里面的`main`属性对应的入口模块,该入口模块即为加载的第三方模块。
3. 如果在要加载的第三方包中没有找到`package.json`文件或者是`package.json`文件中没有`main`属性,则默认加载第三方包中的`index.js`文件。
4. 如果在加载第三方模块的文件的同级目录没有找到`node_modules`文件夹,或者以上所有情况都没有找到,则会向上一级父级目录下查找`node_modules`文件夹,查找规则如上一致。
5. 如果一直找到该模块的磁盘根路径都没有找到,则会报错:`can not find module xxx`。
Npm
  • NPM 出现了两层概念:
    • 一层含义是 Node 的开放式模块登记和管理系统,亦可以说是一个生态圈,一个社区。
    • 另一层含义是 Node 默认的模块管理器,是一个命令行下的软件,用来安装和管理 Node 模块。
  • 常用命令
npm init
npm install/i 包名 -g (uninstall, update)
npm install 包名 -g --save-dev/-D(uninstall, update)
npm list -g (不加-g,列举当前目录下的已安装的包)
npm info 包名 (详细信息)
npm info 包名 version (最新版本)
npm install 包名@版本 (安装指定版本)
npm outdated (检查包是否已经过期)

^2.1.0 npm i 会安装 2.*.* 最新版本
~2.1.0 npm i 会安装 2.1.* 最新版本
*      npm i 会安装 最新版本
  • npm脚本
    • npm 允许在package.json文件里面,使用scripts字段定义脚本命令。package.json 里面的scripts 字段是一个对象。它的每一个属性,对应一段脚本。定义在package.json里面的脚本,就称为 npm 脚本。
yarn
# 对比npm: 
# 速度更快,yarn缓存了每个下载的包,所以再次使用时无需重复下载。同时利用并行下载以最大化资源利用率,因此安装速度更快
# 超级安全:在执行代码前,yarn会通过算法校验每个安装包的完整性

yarn init
yarn add [package]
yarn add [package]@[version]
yarn add [package] --dev

yarn upgrade [package]@[version]

yarn remove [package]

三、内置模块

http模块
1、简单引用
// 引入http模块
cosnt http = require('http')

// 创建服务器
const server = http.createServer((req, res) => {
  // req 接受浏览器的参数
  // res 返回渲染的内容
  res.write('Hello world')
  // 告知浏览器返回结束
  res.end()
}).listen(3000, ()=> {
  console.log('Server Start')
})

// 创建客户端
const client = http.get('http://loalhost:3000', (res) => {
  res.pipe(process.stdout)
})

/*
- server:http.Server实例,用来提供服务,处理客户端的请求。
- client:http.ClientReques实例,用来向服务端发起请求。
- serverReq/clientRes,都是 http.IncomingMessage实例。
    serverReq 用来获取客户端请求的相关信息,如request header;
    clientRes 用来获取服务端返回的相关信息,比如response header。
- serverRes:http.ServerResponse实例
*/
2、http.IncomingMessage、http.ServerResponse
  • http.ServerResponse 实例。服务端通过http.ServerResponse 实例,来给请求方发送数据。包括发送响应表头,发送响应主体等。
  • http.IncomingMessage 实例
    • 在server端:获取请求发送方的信息,比如请求方法、路径、传递的数据等。
    • 在client端:获取 server 端发送过来的信息,比如请求方法、路径、传递的数据等。
    • http.IncomingMessage实例 有三个属性需要注意:method、statusCode、statusMessage。
      • method:只在 server 端的实例有(也就是 serverReq.method)
      • statusCode/statusMessage:只在 client 端 的实例有(也就是 clientRes.method)
3、res
  • 接受到来自客户端的http请求后,向客户端返回正确的响应内容,这就是res的职责。
  • 返回的内容包括:状态代码/状态描述信息、响应头部、响应主体。
// 1、状态代码/状态描述信息
res.writeHead(200, 'ok')

// 或者

res.statusCode = 200
res.statusMessage = 'ok'

/* 
两者差不多,差异点在于
1. res.writeHead() 可以提供额外的功能,比如设置响应头部。
2. 当响应头部发送出去后,res.statusCode/res.statusMessage 会被设置成已发送出去的 状态代码/状态描述信息。
*/

// 2、响应头部
res.writeHead(200, 'ok', {
  'Content-type':'text/plain'
})
res.setHeader('Content-type', 'text/plain')

/*
两者的差异点在哪里呢?
1. res.writeHead() 不单单是设置header。
2. 已经通过 res.setHeader() 设置了header,当通过 res.writeHead() 设置同名header,res.writeHead() 的设置会覆盖之前的设置。
3. 通过res.writeHead()设置了header,再通过res.setHeader()设置同名header会报错
*/

// 3、设置响应主体
// response.write(chunk[,encoding][,callback])
/*
- chunk:响应主体的内容,可以是string,也可以是buffer。当为string时,encoding参数用来指明编码方式。(默认是utf8)
- encoding:编码方式,默认是 utf8。
- callback:当响应体flushed时触发。
*/
res.write('hello')
// response.end([data][,encoding][,callback])
/*
res.end() 的用处是告诉nodejs,header、body都给你了,这次响应就到这里吧
*/
res.end('hello')

4、req
类型名称服务端客户端
事件aborted
事件close
属性headers
属性rawHeaders
属性statusCode
属性statusMessage
属性httpVersion
属性url
属性socket
方法.destroy()
方法.setTimeout()
// 服务端获取HTTP版本、请求方法、请求地址、请求头部
req.url
req.httpVersion
req.method
req.headers
https模块
简单用法
// 客户端
const https = require('https')
const fs = require('fs');

https.get('https://www.baidu.com', (res) => {
  console.log('status code: ' + res.statusCode);
  console.log('headers: ' + JSON.stringify(res.headers));
  res.on('data', function(data){
      process.stdout.write(data);
  });
}).on('error', (err)=> {
  console.log(err)
})

// 服务端需要证书
/*
1.创建个目录存放证书。

mkdir cert
cd cert

2.生成私钥。

openssl genrsa -out chyingp-key.pem 2048

3.生成证书签名请求(csr是 Certificate Signing Request的意思)。

openssl req -new \
  -sha256
  -key chyingp-key.key.pem \
  -out chyingp-csr.pem \
  -subj "/C=CN/ST=Guandong/L=Shenzhen/O=YH Inc/CN=www.chyingp.com"

4.生成证书。

openssl x509 \
  -req -in chyingp-csr.pem \
  -signkey chyingp-key.pem \
  -out chyingp-cert.pem
*/

const options = {
    key: fs.readFileSync('./cert/chyingp-key.pem'), // 私钥
    cert: fs.readFileSync('./cert/chyingp-cert.pem') // 证书
};

const server = https.createServer(options, function(req, res){
    res.end('这是来自HTTPS服务器的返回');
}).listen(3000, () => {
  console.log('server start')
})

url模块
const url = require('url')

// 1、url.parse(废弃)
// 解析url,生成url对象
url.parse(req.url)

// 2、url.format(废弃)
// 将url对象拼接成url
const urlObject = {}
url.format(urlObject)

//3、url.resolve(废弃)
url.resolve('/one/two/three', 'four');         // '/one/two/four'
url.resolve('http://example.com/', '/one');    // 'http://example.com/one'
url.resolve('http://example.com/one', '/two'); // 'http://example.com/two'

// 4、新版写法
new URL()
URL 接口(代替内置模块url使用)
  • nodejs内置模块url有些方法要被废弃,我们使用URL类代替
  • 浏览器原生提供URL()接口,它是一个构造函数,用来构造、解析和编码 URL。一般情况下,通过window.URL可以拿到这个构造函数。
1、Url模块和Url类
属性url模块URL类
protocol
host
port
hostname
search
query-
path-
pathname
href
hash
origin-
// 打印两个对象的输出
// url模块,url.parse('link')
{
  protocol: 'https:',
  slashes: true,
  auth: null,
  host: 'm.shop.com',
  port: null,
  hostname: 'm.shop.com',
  hash: '#detail',
  search: '?id=4433&name=%E6%9D%8E%E5%A4%87&directCompanyId=&mobile=18951431099',
  query: 'id=4433&name=%E6%9D%8E%E5%A4%87&directCompanyId=&mobile=18951431099',
  pathname: '/home/share',
  path: '/home/share?id=4433&name=%E6%9D%8E%E5%A4%87&directCompanyId=&mobile=18951431099',
  href: 'https://m.shop.com/home/share?id=4433&name=%E6%9D%8E%E5%A4%87&directCompanyId=&mobile=18951431099#detail'
}
// new URL()
{
  href: 'https://m.shop.com/home/share?id=4433&name=%E6%9D%8E%E5%A4%87&directCompanyId=&mobile=18951431099#detail',
  origin: 'https://m.shop.com',
  protocol: 'https:',
  username: '',
  password: '',
  host: 'm.shop.com',
  hostname: 'm.shop.com',
  port: '',
  pathname: '/home/share',
  search: '?id=4433&name=%E6%9D%8E%E5%A4%87&directCompanyId=&mobile=18951431099',
  searchParams: URLSearchParams {
    'id' => '4433',
    'name' => '李备',
    'directCompanyId' => '',
    'mobile' => '18951431099' },
  hash: '#detail'
}
URL()构造函数
  • URL()作为构造函数,可以生成 URL 实例。它接受一个表示 URL 的字符串作为参数。如果参数不是合法的 URL,会报错
var url = new URL('http://www.example.com/index.html');
url.href
// "http://www.example.com/index.html"
queryString 模块
const queryString = require('querystring')
const qs = 'x=3&y=4'

// 1、parse
queryString.parse(qs)

// 2、stringify
const qo = {
  x:3,
  y:4
}

queryString.stringify(qo)
URLSearchParams 对象(代替内置模块querystring使用)
  • URLSearchParams对象是浏览器的原生对象,用来构造、解析和处理 URL 的查询字符串(即 URL 问号后面的部分)。

  • 它本身也是一个构造函数,可以生成实例。参数可以为查询字符串,起首的问号?有没有都行,也可以是对应查询字符串的数组或对象。

qs模块

qs是一个npm仓库所管理的包,可通过npm install qs命令进行安装.

  1. qs.parse()将URL解析成对象的形式
  2. qs.stringify()将对象 序列化成URL的形式,以&进行拼接
const qs = require('qs');

qs.parse()
const str = "username='admin'&password='123456'";
console.log(qs.parse(str)); 
// Object { username: "admin", password: "123456" }

qs.stringify()
const a = qs.stringify({ username: 'admin', password: '123456' });
console.log(a); 
// username=admin&password=123456
// qs.stringify() 和JSON.stringify()有什么区别?

var a = {name:'hehe',age:10};
// qs.stringify序列化结果如
// name=hehe&age=10
// --------------------
// 而JSON.stringify序列化结果如下:
// "{"a":"hehe","age":10}"
path模块
  • path模块用于路径处理
获取路径/文件名/扩展名
  • 获取路径:path.dirname(filepath)
  • 获取文件名:path.basename(filepath)
  • 获取扩展名:path.extname(filepath)
路径组合
  • path.join([…paths])
  • path.resolve([…paths])
  • path.resolve 和 path.join 都是属于 path 核心模块下的方法,用来拼接路径
    • 如果 dirname 是以 ./ 、…/、不加 / 开头的话,那么 resolve 会找到磁盘下的根目录
    • 如果 basename 是以 / 开头的,那么 resolve 就会直接返回 basename
常见路径
  • __dirname:这是一个常量,表示:当前执行文件所在完整目录
  • __filename:这是一个常量。表示:当前执行文件的完整目录 + 文件名
  • process.cwd:获取当前执行 Node命令 时的目录名。
fs模块
Node.js 中的同步和异步的区别

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

区别:

  • 同步调用会阻塞代码的执行,异步则不会。
  • 异步调用会将 读取任务 下达到任务队列,直到任务执行完成才会回调。
  • 异常处理方面:同步必须使用 try catch 方式,异步可以通过回调函数的第一个参数。【重要】
文件读取
// 同步读取
const fs = require('fs')
try{
    const data = fs.readFileSync('./fileForRead.txt', 'utf8');
    console.log('文件内容: ' + data);
}catch(err){
    console.error('读取文件出错: ' + err.message);
}

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

// fs/promise
import { readFile } from 'fs/promises';
try {
  const contents = await readFile(filePath, { encoding: 'utf8' });
  console.log(contents);
} catch (err) {
  console.error(err.message);
}
文件写入
// 同步写入
const fs = require('fs')
try{
    // 如果文件不存在,则创建文件;如果文件存在,则覆盖文件内容;
    fs.writeFileSync('./fileForWrite1.txt', 'hello world', 'utf8');
    console.log('文件写入成功');
}catch(err){
    throw err;
}

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

// 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);
}


文件是否存在
  • 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()`除了判断文件是否存在(默认模式),还可以用来判断文件的权限。
备忘:`fs.constants.F_OK`等常量无法获取(node v6.1,mac 10.11.4下,`fs.constants`是`undefined`)
*/

// 同步
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');
}
删除文件
// 异步
const 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
}
创建目录
// 异步
const fs = require('fs')

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

// 同步
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);
}

遍历目录
  • fs.readdirSync()只会读一层,所以需要判断文件类型是否目录,如果是,则进行递归遍历。
删除目录
// 删除目录(前提没有文件在里面)
fs.rmdir('./avatar', err => {
  if (err && err.code === 'ENOENT') {
    console.log('目录不存在');
  }
});
删除整个目录
//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');
});
文件重命名
// 异步
const fs = require('fs')
fs.rename('./hello', './world', function(err){
    if(err) throw err;
    console.log('重命名成功');
});

// 同步
fs.renameSync('./world', './hello');

// promises
import { rename } from 'fs/promises';

try {
  await rename('./world', './hello');
  console.log(`rename`);
} catch (err) {
  console.error(err.message);
}
获取文件状态

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() – 是否目录
events模块
  • Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件
// 引入 events 模块
var EventEmitter = require('events');
// 创建 eventEmitter 对象
var event = new EventEmitter();

// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);
// 触发事件
eventEmitter.emit('eventName');
stream模块
  • stream是Node.js提供的又一个仅在服务区端可用的模块,目的是支持“流”这种数据结构
读取流
const fs = require('fs');

//创建读取流
let rs = fs.createReadStream('hello.txt', 'utf-8');

rs.on('open', function () {
  console.log('读取的文件已打开');
}).on('close', function () {
  console.log('读取流结束');
}).on('error', err => {
  console.log(err);
}).on('data', function (chunk) {
  //每一批数据流入完成
  console.log('单批数据流入:' + chunk.length);
  console.log(chunk);
});

// 要注意,`data`事件可能会有多次,每次传递的`chunk`是流的一部分数据。


// 写入流
// 要以流的形式写入文件,只需要不断调用`write()`方法,最后以`end()`结束
let ws = fs.createWriteStream('hello.txt', 'utf-8');

//监听文件打开事件
ws.on('open', function () {
  console.log('文件打开');
});

//监听文件关闭事件
ws.on('close', function () {
  console.log('文件写入完成,关闭');
});

//文件流式写入
ws.write('helloworld1!', function (err) {
  if (err) {
    console.log(err);
  } else {
    console.log('内容1流入完成');
  }
});
ws.write('helloworld2!', function (err) {
  if (err) {
    console.log(err);
  } else {
    console.log('内容2流入完成');
  }
});

//文件写入完成
ws.end(function () {
  console.log('文件写入关闭');
});

-pipe 就像可以把两个水管串成一个更长的水管一样,两个流也可以串起来。一个Readable流和一个Writable流串起来后,所有的数据自动从Readable流进入Writable流,这种操作叫pipe

  • 在Node.js中,Readable流有一个pipe()方法,就是用来干这件事的。

  • 让我们用pipe()把一个文件流和另一个文件流串起来,这样源文件的所有数据就自动写入到目标文件里了,所以,这实际上是一个复制文件的程序:

const fs = require('fs');

//创建读取流
let rs = fs.createReadStream('video.mp4');
let ws = fs.createWriteStream('b.mp4');

rs.on('close', function () {
  console.log('读取流结束');
});

rs.pipe(ws);
zlib模块
// 压缩
var fs = require('fs');
var zlib = require('zlib');

var gzip = zlib.createGzip();

var readstream = fs.createReadStream('./extra/fileForCompress.txt');
var writestream = fs.createWriteStream('./extra/fileForCompress.txt.gz');

readstream.pipe(gzip).pipe(writestream);

// 解压
var readstream  = fs.createReadStream('./extra/fileForCompress.txt.gz');
var writestream  = fs.createWriteStream('./extra/fileForCompress1.txt');

readstream.pipe(gunzip).pipe(writestream);

// 首先判断 是否包含 **accept-encoding** 首部,且值为**gzip**。
//  否:返回未压缩的文件。
//  是:返回gzip压缩后的文件。
ctypto
  • crypto模块的目的是为了提供通用的加密和哈希算法。用纯JavaScript代码实现这些功能不是不可能,但速度会非常慢。Nodejs用C/C++实现这些算法后,通过cypto这个模块暴露为JavaScript接口,这样用起来方便,运行速度也快
hash
  • hash.digest([encoding]):计算摘要。encoding可以是hexlatin1或者base64。如果声明了encoding,那么返回字符串。否则,返回Buffer实例。注意,调用hash.digest()后,hash对象就作废了,再次调用就会出错。

  • hash.update(data[, input_encoding]):input_encoding可以是utf8ascii或者latin1。如果data是字符串,且没有指定 input_encoding,则默认是utf8。注意,hash.update()方法可以调用多次。

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

var content = fs.readFileSync('./test.txt', {encoding: 'utf8'});
var hash = crypto.createHash('sha256');
var output;

hash.update(content);
output = hash.digest('hex'); 
//或
hash.setEncoding('hex');
input.pipe(hash).pipe(process.stdout)

console.log(output);
// 输出内容为:
// b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9

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

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

相关文章

为什么现在的大学生很难真正学好LabVIEW编程?

学习LabVIEW编程对大学生来说可能存在以下挑战: 学习曲线陡峭:尽管LabVIEW提供直观的图形化编程环境,便于初学者入门,但要深入掌握其高级功能和复杂应用,仍需要投入大量时间和精力。随着学习的深入,概念和应…

CAN与CANFD的区别

CAN概念: CAN,全称为Controller Area Network,即控制器局域网络,是一种用于汽车电子系统中的串行通信协议。它由德国电气工程师协会(Bosch)在1983年开发,并在1986年正式推出。CAN协议主要用于汽…

牛客:Holding Two,Inverse Pair,Counting Triangles

Holding Two 题目描述 登录—专业IT笔试面试备考平台_牛客网 ​​运行代码 #include<bits/stdc.h> using namespace std; const int N3e45; string s1,s2; int main(){int n,m;cin>>n>>m;for(int i0;i<m;i){if(i&1){s10;s21;} else{s11;s20;} }fo…

架构师:Spring Cloud Gateway 的技术指南

1、简述 Spring Cloud Gateway 是 Spring Cloud 生态系统中的一个重要组件,作为微服务架构的 API 网关,它为路由、限流、安全、监控等功能提供了全面支持。相比传统的 Zuul 网关,Spring Cloud Gateway 使用了非阻塞的 WebFlux 框架,性能上有了显著提升,并且提供了更现代化…

BLE MESH学习2——自定义MESH网络架构思考

BLE MESH学习2——自定义MESH网络架构思考 基于对WCH CH582这款单片机的了解&#xff0c;其可以实现mesh配网、朋友节点、低功耗节点和中继节点的角色&#xff0c;基本功能无问题。在此基础上&#xff0c;考虑满足IoT需求的MESH架构设计&#xff0c;作为后续设计的“白皮书”。…

构建流媒体管道:利用 Docker 部署 Nginx-RTMP 从 FFmpeg RTMP 推流到 HLS 播放的完整流程

最近要实现一个类似导播台的功能&#xff0c;于是我先用 FFmpeg 实现一个参考对照的 Demo&#xff0c;我将其整理为一篇文章&#xff0c;方便后续大家或者和自己参考&#xff01; 1、软件工具介绍 本次部署相关软件 / 工具如下&#xff1a; FFmpeg&#xff1a;全称是 Fast Fo…

java脚手架系列1--模块化、多环境

之所以想写这一系列&#xff0c;是因为之前工作过程中有几次项目是从零开始搭建的&#xff0c;而且项目涉及的内容还不少。在这过程中&#xff0c;遇到了很多棘手的非业务问题&#xff0c;在不断实践过程中慢慢积累出一些基本的实践经验&#xff0c;认为这些与业务无关的基本的…

kkFileView 4.4.0最新版本发行版安装包部署及使用文档

kkFileView为文件文档在线预览解决方案&#xff0c;该项目使用流行的spring boot搭建&#xff0c;易上手和部署&#xff0c;基本支持主流办公文档的在线预览&#xff0c;如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等 一. 下载&部署 下载最新发行包&…

网络层协议 --- IP

序言 在这篇文章中我们将介绍 IP协议&#xff0c;经过这篇文章的学习&#xff0c;我们就会了解运营商到底是如何为我们提供服务的以及平时我们所说的内网&#xff0c;公网到底又是什么&#xff0c;区别是什么&#xff1f; IP 地址的基本概念 1. IP 地址的定义 每一个设备接入…

Java中String类的常见操作Api

目录 String类的常见操作 1).int indexOf (char 字符) 2).int lastIndexOf(char 字符) 3).int indexOf(String 字符串) 4).int lastIndexOf(String 字符串) 5).char charAt(int 索引) 6).Boolean endWith(String 字符串) 7).int length() 8).boolean equals(T 比较对象) 9).b…

【2024】作为前端开发,必须掌握的 Vue3 的 5 个组合式 API 方法

引言&#xff1a;2024 你还不知道 Vue3 的 defineProps、defineEmits、defineExpose、defineOptions 和 defineSlots 吗&#xff1f;这几个 Vue3 组合式 API 方法不仅开发常用&#xff08;涉及组件通信、组件复用等&#xff09;&#xff0c;在面试中也是不可或缺的一部分&#…

SpringBoot实现电子文件签字+合同系统!

一、前言 二、项目源码及部署 1、项目结构及使用框架 2、项目下载及部署 三、功能展示 一、前言 今天公司领导提出一个功能,说实现一个文件的签字+盖章功能,然后自己进行了简单的学习,对文档进行数字签名与签署纸质文档的原因大致相同,数字签名通过使用计算机加密来验证 (…

LabVIEW提高开发效率技巧----阻塞时钟

在LabVIEW开发中&#xff0c;阻塞时钟&#xff08;Blocking Timed Loops&#xff09;是一种常见且强大的技术&#xff0c;尤其适用于时间关键的应用。在这些应用中&#xff0c;精确控制循环的执行频率是关键任务。阻塞时钟通过等待循环的执行完成后再进入下一次迭代&#xff0c…

鸿蒙 Next 实战: 烟花模拟器

前言 通过上一篇文章可以看出&#xff0c;要在鸿蒙应用中实现特别炫的特效还是比较复杂。动画固然重要&#xff0c;但如果在赶工期的情况下&#xff0c;大家都会优先业务&#xff0c;那有没有简单快速的方法呢&#xff1f; 有的&#xff0c;也用像 Android 和 iOS 里 WebView …

.Net Core 接口或网站发布到IIS

将.Net Core 接口或网站发布到IIS上&#xff0c;需要遵循一系列步骤来确保正确配置和部署。下面将以.NET Core 3.1的api接口发布示范&#xff1a; 一、环境准备 安装.NET Core 3.1 SDK和运行时&#xff1a; 在服务器上安装.NET Core 3.1 SDK&#xff08;如果需要在服务器上编译…

宝兰德亮相2024国际信息通信展:数智创新,信创力量!

9月25日-27日&#xff0c;2024中国国际信息通信展览会在北京国家会议中心隆重召开。本届展会以“推动数实深度融合&#xff0c;共筑新质生产力”为主题&#xff0c;全面展示信息通信业发展最新成果。作为国内领先的基础软件供应商&#xff0c;宝兰德再度闪耀会场&#xff0c;在…

[ROS】rqt工具箱

作用&#xff1a; 可以方便的实现 ROS 可视化调试&#xff0c;并且在同一窗口中打开多个部件&#xff0c;提高开发效率&#xff0c;优化用户体验。 组成&#xff1a; rqt工具箱组成有三大部分 rqt 核心实现&#xff0c;开发人员无需关注 rqt_common_plugins rqt…

Gated Transformer Networks for Multivariate Time Series Classification

博客贡献人 徐宁 作者 Minghao Liu , Shengqi Ren , Siyuan Ma , Jiahui Jiao , Yizhou Chen , Zhiguang Wang(Facebook AI) and Wei Song∗ 标签 多元时间序列分类&#xff0c;Transformer&#xff0c;门控 摘要 用于时间序列分类的深度学习模型&#xff08;主要是卷积网…

GO网络编程(七):海量用户通信系统5:分层架构

P323开始&#xff08;尚硅谷GO教程&#xff09;老韩又改目录结构了&#xff0c;没办法&#xff0c;和之前一样&#xff0c;先说下目录结构&#xff0c;再给代码&#xff0c;部分代码在之前讲过&#xff0c;还有知识的话由于本人近期很忙&#xff0c;所以这些就不多赘述了&#…