Node.js
是一个开源与跨平台的 JavaScript
运行时环境
在浏览器外运行 V8 JavaScript 引擎(Google Chrome 的内核),利用事件驱动、非阻塞和异步输入输出模型等技术提高性能
可以理解为 Node.js
就是一个服务器端的、非阻塞式I/O的、事件驱动的JavaScript
运行环境
Nodejs
采用了非阻塞型I/O
机制,在做I/O
操作的时候不会造成任何的阻塞,当完成之后,以时间的形式通知执行操作
例如在执行了访问数据库的代码之后,将立即转而执行其后面的代码,把数据库返回结果的处理代码放在回调函数中,从而提高了程序的执行效率
事件驱动就是当进来一个新的请求的时,请求将会被压入一个事件队列中,然后通过一个循环来检测队列中的事件状态变化,如果检测到有状态变化的事件,那么就执行该事件对应的处理代码,一般都是回调函数
比如读取一个文件,文件读取完毕后,就会触发对应的状态,然后通过对应的回调函数来进行处理
优点:
因为Nodejs
是单线程,带来的缺点有:
借助Nodejs
的特点和弊端,其应用场景分类如下:
I/O
,不善于计算。因为Nodejs是一个单线程,如果计算(同步)太多,则会阻塞这个线程具体场景可以表现为如下:
json
的API其实,Nodejs
能实现几乎一切的应用,只考虑适不适合使用它
在浏览器 JavaScript
中,通常window
是全局对象, 而 Nodejs
中的全局对象是 global
在NodeJS
里,是不可能在最外层定义一个变量,因为所有的用户代码都是当前模块的,只在当前模块里可用,但可以通过exports
对象的使用将其传递给模块外部
所以,在NodeJS
中,用var
声明的变量并不属于全局的变量,只在当前模块生效
像上述的global
全局对象则在全局作用域中,任何全局变量、函数、对象都是该对象的一个属性值
将全局对象分成两类:
下面给出一些常见的全局对象:
可以处理二进制以及非Unicode
编码的数据
在Buffer
类实例化中存储了原始数据。Buffer
类似于一个整数数组,在V8堆原始存储空间给它分配了内存
一旦创建了Buffer
实例,则无法改变大小
进程对象,提供有关当前进程的信息和控制
包括在执行node
程序进程时,如果需要传递参数,我们想要获取这个参数需要在process
内置对象中
启动进程:
node index.js 参数1 参数2 参数3
index.js文件如下:
process.argv.forEach((val, index) => {
console.log(`${index}: ${val}`);
});
输出如下:
/usr/local/bin/node
/Users/mjr/work/node/process-args.js
参数1
参数2
参数3
除此之外,还包括一些其他信息如版本、操作系统等
用来打印stdout
和stderr
最常用的输入内容的方式:console.log
console.log("hello");
清空控制台:console.clear
console.clear
打印函数的调用栈:console.trace
function test() {
demo();
}
function demo() {
foo();
}
function foo() {
console.trace();
}
test();
设置定时器与清除定时器
setInterval(callback, delay[, ...args])
callback
每delay
毫秒重复执行一次
clearInterval
则为对应发取消定时器的方法
设置延时器与清除延时器
setTimeout(callback,delay[,...args])
callback
在delay
毫秒后执行一次
clearTimeout
则为对应取消延时器的方法
全局命名空间对象,墙面讲到的process
、console
、setTimeout
等都有放到global
中
console.log(process === global.process) // true
模块级别的全局对象
这些全局对象是模块中的变量,只是每个模块都有,看起来就像全局变量,像在命令交互中是不可以使用,包括:
获取当前文件所在的路径,不包括后面的文件名
从 /Users/mjr
运行 node example.js
:
console.log(__dirname);
// 打印: /Users/mjr
获取当前文件所在的路径和文件名称,包括后面的文件名称
从 /Users/mjr
运行 node example.js
:
console.log(__filename);
// 打印: /Users/mjr/example.js
module.exports
用于指定一个模块所导出的内容,即可以通过 require()
访问的内容
exports.name = name;
exports.age = age;
exports.sayHello = sayHello;
对当前模块的引用,通过module.exports
用于指定一个模块所导出的内容,即可以通过 require()
访问的内容
用于引入模块、 JSON
、或本地文件。可以从 node_modules
引入模块。
可以使用相对路径引入本地模块或JSON
文件,路径会根据__dirname
定义的目录名或当前工作目录进行处理
process
对象是一个全局变量,提供了有关当前 Node.js
进程的信息并对其进行控制,作为一个全局变量
我们都知道,进程计算机系统进行资源分配和调度的基本单位,是操作系统结构的基础,是线程的容器
当我们启动一个js
文件,实际就是开启了一个服务进程,每个进程都拥有自己的独立空间地址、数据栈,像另一个进程无法访问当前进程的变量、数据结构,只有数据通信后,进程之间才可以数据共享
由于JavaScript
是一个单线程语言,所以通过node xxx
启动一个文件后,只有一条主线程
关于process
常见的属性有如下:
EventLoop
时经常为会提到下面再稍微介绍下某些方法的使用:
返回当前 Node
进程执行的目录
一个Node
模块 A
通过 NPM 发布,项目 B
中使用了模块 A
。在 A
中需要操作 B
项目下的文件时,就可以用 process.cwd()
来获取 B
项目的路径
在终端通过 Node 执行命令的时候,通过 process.argv
可以获取传入的命令行参数,返回值是一个数组:
所以,我们只要从 process.argv[2]
开始获取就好了
const args = process.argv.slice(2);
返回一个对象,存储当前环境相关的所有信息,一般很少直接用到。
一般我们会在 process.env
上挂载一些变量标识当前的环境。比如最常见的用 process.env.NODE_ENV
区分 development
和 production
在 vue-cli
的源码中也经常会看到 process.env.VUE_CLI_DEBUG
标识当前是不是 DEBUG
模式
process.nextTick() 是微任务
我们知道NodeJs
是基于事件轮询,在这个过程中,同一时间只会处理一件事情
在这种处理模式下,process.nextTick()
就是定义出一个动作,并且让这个动作在下一个事件轮询的时间点上执行
例如下面例子将一个foo
函数在下一个时间点调用
function foo() {
console.error('foo');
}
process.nextTick(foo);
console.error('bar');
输出结果为bar
、foo
虽然下述方式也能实现同样效果:
setTimeout(foo, 0);
console.log('bar');
两者区别在于:
fs(filesystem),该模块提供本地文件的读写能力,基本上是POSIX
文件操作命令的简单包装
可以说,所有与文件的操作都是通过fs
核心模块实现
导入模块如下:
const fs = require('fs');
这个模块对所有文件系统操作提供异步(不具有sync
后缀)和同步(具有 sync
后缀)两种操作方式,而供开发者选择
在计算机中有关于文件的知识:
针对文件所有者、文件所属组、其他用户进行权限分配,其中类型又分成读、写和执行,具备权限位4、2、1,不具备权限为0
如在linux
查看文件权限位:
drwxr-xr-x 1 PandaShen 197121 0 Jun 28 14:41 core
-rw-r--r-- 1 PandaShen 197121 293 Jun 23 17:44 index.md
在开头前十位中,d
为文件夹,-
为文件,后九位就代表当前用户、用户所属组和其他用户的权限位,按每三位划分,分别代表读(r)、写(w)和执行(x),- 代表没有当前位对应的权限
标识位代表着对文件的操作方式,如可读、可写、即可读又可写等等,如下表所示:
符号 | 含义 |
---|---|
r | 读取文件,如果文件不存在则抛出异常。 |
r+ | 读取并写入文件,如果文件不存在则抛出异常。 |
rs | 读取并写入文件,指示操作系统绕开本地文件系统缓存。 |
w | 写入文件,文件不存在会被创建,存在则清空后写入。 |
wx | 写入文件,排它方式打开。 |
w+ | 读取并写入文件,文件不存在则创建文件,存在则清空后写入。 |
wx+ | 和 w+ 类似,排他方式打开。 |
a | 追加写入,文件不存在则创建文件。 |
ax | 与 a 类似,排他方式打开。 |
a+ | 读取并追加写入,不存在则创建。 |
ax+ | 与 a+ 类似,排他方式打开。 |
操作系统会为每个打开的文件分配一个名为文件描述符的数值标识,文件操作使用这些文件描述符来识别与追踪每个特定的文件
Window
系统使用了一个不同但概念类似的机制来追踪资源,为方便用户,NodeJS
抽象了不同操作系统间的差异,为所有打开的文件分配了数值的文件描述符
在 NodeJS
中,每操作一个文件,文件描述符是递增的,文件描述符一般从 3
开始,因为前面有 0
、1
、2
三个比较特殊的描述符,分别代表 process.stdin
(标准输入)、process.stdout
(标准输出)和 process.stderr
(错误输出)
下面针对fs
模块常用的方法进行展开:
同步读取,参数如下:
结果为返回文件的内容
const fs = require("fs");
let buf = fs.readFileSync("1.txt");
let data = fs.readFileSync("1.txt", "utf8");
console.log(buf); // <Buffer 48 65 6c 6c 6f>
console.log(data); // Hello
异步读取方法 readFile
与 readFileSync
的前两个参数相同,最后一个参数为回调函数,函数内有两个参数 err
(错误)和 data
(数据),该方法没有返回值,回调函数在读取文件成功后执行
const fs = require("fs");
fs.readFile("1.txt", "utf8", (err, data) => {
if(!err){
console.log(data); // Hello
}
});
同步写入,有三个参数:
const fs = require("fs");
fs.writeFileSync("2.txt", "Hello world");
let data = fs.readFileSync("2.txt", "utf8");
console.log(data); // Hello world
异步写入,writeFile
与 writeFileSync
的前三个参数相同,最后一个参数为回调函数,函数内有一个参数 err
(错误),回调函数在文件写入数据成功后执行
const fs = require("fs");
fs.writeFile("2.txt", "Hello world", err => {
if (!err) {
fs.readFile("2.txt", "utf8", (err, data) => {
console.log(data); // Hello world
});
}
});
参数如下:
const fs = require("fs");
fs.appendFileSync("3.txt", " world");
let data = fs.readFileSync("3.txt", "utf8");
异步追加写入方法 appendFile
与 appendFileSync
的前三个参数相同,最后一个参数为回调函数,函数内有一个参数 err
(错误),回调函数在文件追加写入数据成功后执行
const fs = require("fs");
fs.appendFile("3.txt", " world", err => {
if (!err) {
fs.readFile("3.txt", "utf8", (err, data) => {
console.log(data); // Hello world
});
}
});
同步拷贝
const fs = require("fs");
fs.copyFileSync("3.txt", "4.txt");
let data = fs.readFileSync("4.txt", "utf8");
console.log(data); // Hello world
异步拷贝
const fs = require("fs");
fs.copyFile("3.txt", "4.txt", () => {
fs.readFile("4.txt", "utf8", (err, data) => {
console.log(data); // Hello world
});
});
同步创建,参数为一个目录的路径,没有返回值,在创建目录的过程中,必须保证传入的路径前面的文件目录都存在,否则会抛出异常
// 假设已经有了 a 文件夹和 a 下的 b 文件夹
fs.mkdirSync("a/b/c")
异步创建,第二个参数为回调函数
fs.mkdir("a/b/c", err => {
if (!err) console.log("创建成功");
});
在Node
应用中,需要处理网络协议、操作数据库、处理图片、接收上传文件等,在网络流和文件的操作中,要处理大量二进制数据,而Buffer
就是在内存中开辟一片区域(初次初始化为8KB),用来存放二进制数据
在上述操作中都会存在数据流动,每个数据流动的过程中,都会有一个最小或最大数据量
如果数据到达的速度比进程消耗的速度快,那么少数早到达的数据会处于等待区等候被处理。反之,如果数据到达的速度比进程消耗的数据慢,那么早先到达的数据需要等待一定量的数据到达之后才能被处理
这里的等待区就指的缓冲区(Buffer),它是计算机中的一个小物理单位,通常位于计算机的 RAM
中
简单来讲,Nodejs
不能控制数据传输的速度和到达时间,只能决定何时发送数据,如果还没到发送时间,则将数据放在Buffer
中,即在RAM
中,直至将它们发送完毕
上面讲到了Buffer
是用来存储二进制数据,其的形式可以理解成一个数组,数组中的每一项,都可以保存8位二进制:00000000
,也就是一个字节
例如:
const buffer = Buffer.from("why")
Buffer
类在全局作用域中,无须require
导入
创建Buffer
的方法有很多种,我们讲讲下面的两种常见的形式:
const b1 = Buffer.from('10');
const b2 = Buffer.from('10', 'utf8');
const b3 = Buffer.from([10]);
const b4 = Buffer.from(b3);
console.log(b1, b2, b3, b4); // <Buffer 31 30> <Buffer 31 30> <Buffer 0a> <Buffer 0a>
const bAlloc1 = Buffer.alloc(10); // 创建一个大小为 10 个字节的缓冲区
const bAlloc2 = Buffer.alloc(10, 1); // 建一个长度为 10 的 Buffer,其中全部填充了值为 `1` 的字节
console.log(bAlloc1); // <Buffer 00 00 00 00 00 00 00 00 00 00>
console.log(bAlloc2); // <Buffer 01 01 01 01 01 01 01 01 01 01>
在上面创建buffer
后,则能够toString
的形式进行交互,默认情况下采取utf8
字符编码形式,如下
const buffer = Buffer.from("你好");
console.log(buffer);
// <Buffer e4 bd a0 e5 a5 bd>
const str = buffer.toString();
console.log(str);
// 你好
如果编码与解码不是相同的格式则会出现乱码的情况,如下:
const buffer = Buffer.from("你好","utf-8 ");
console.log(buffer);
// <Buffer e4 bd a0 e5 a5 bd>
const str = buffer.toString("ascii");
console.log(str);
// d= e%=
当设定的范围导致字符串被截断的时候,也会存在乱码情况,如下:
const buf = Buffer.from('Node.js 技术栈', 'UTF-8');
console.log(buf) // <Buffer 4e 6f 64 65 2e 6a 73 20 e6 8a 80 e6 9c af e6 a0 88>
console.log(buf.length) // 17
console.log(buf.toString('UTF-8', 0, 9)) // Node.js �
console.log(buf.toString('UTF-8', 0, 11)) // Node.js 技
所支持的字符集有如下:
Buffer
的应用场景常常与流的概念联系在一起,例如有如下:
通过流的形式,将一个文件的内容读取到另外一个文件
const fs = require('fs');
const inputStream = fs.createReadStream('input.txt'); // 创建可读流
const outputStream = fs.createWriteStream('output.txt'); // 创建可写流
inputStream.pipe(outputStream); // 管道读写
在一些加解密算法中会遇到使用 Buffer
,例如 crypto.createCipheriv
的第二个参数 key
为 string
或 Buffer
类型
zlib.js
为 Node.js
的核心库之一,其利用了缓冲区(Buffer
)的功能来操作二进制数据流,提供了压缩或解压功能
本文由微信公众号量子前端原创,哈喽比特收录。
文章来源:https://mp.weixin.qq.com/s/_p7vAI6mRp7E_NIONAqFKw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。