day1
1.下载node.js
我下的是LTS长期支持版,比较稳定,安装好之后打开cmd输入node -v就可以查看node版本顺便输入一下npm -v看看npm有没有安好,npm是安装node自动下的后面写vue经常用到。
2.版本管理工具
不支持windows就没下,两个管理工具一个叫nvm另一个叫n(就一个字母没少打)。
3.敲代码!!!
1.如何在 node 环境下运行js代码
创建js文件输入下面的内容,很简单的两个打印之前学js在浏览器端经常用console.log()测试
这次在node环境下运行一下试试。
console.log(11111);
console.log(2222);
打开终端cd到相应的文件夹输入文件夹的前几个字然后按tab可以快速定位到文件夹,切换到js文件的上一层文件夹就行了,输入命令node + 文件夹名 就可以输出了。
PS C:\Users\KABUTO\Desktop\codewhy\node.js\01-js代码运行> node .\index.js
11111
2222
2.给node传递参数
首先node里面有一个process,我们可以打印一下它。
console.log(process);
得到一个很复杂的对象,其他东西先不管,这个大对象里又一个数组argv我们看一下此时的argv。
argv: [
'D:\\node\\node.exe',
'C:\\Users\\KABUTO\\Desktop\\codewhy\\node.js\\02-给node传递参数\\indedx.js'
]
里面只有两个路径,如果在运行的时候传两个值进去会怎么样呢。
node .\indedx.js hello kabuto
此时argv变成了
argv: [
'D:\\node\\node.exe',
'C:\\Users\\KABUTO\\Desktop\\codewhy\\node.js\\02-给node传递参数\\indedx.js',
'hello',
'kabuto'
]
可以看到刚刚传的两个值以字符串的形式存进了argv里,完成了给node传递参数
3.node中的全局对象
两个特殊的全局对象
__dirname 和 __filename,打印一下
console.log(__dirname);
console.log(__filename);
输出
PS C:\Users\KABUTO\Desktop\codewhy\node.js\03-Node中的全局对象> node .\01_特殊的全局对象.js
C:\Users\KABUTO\Desktop\codewhy\node.js\03-Node中的全局对象
C:\Users\KABUTO\Desktop\codewhy\node.js\03-Node中的全局对象\01_特殊的全局对象.js
可以看出第一个是打印出当前执行命令所在文件夹的路径,第二个是当前命令所执行文件的路径.
计时器全局对象
setTimeout,setInterval,setImmediate,process.nextTick,计时器,循环计时器,立即执行计时器,还有个不认识的但上面传值的时候打印过这玩意。
看看谁输出比较快。
setTimeout(()=>{console.log('setTimeout');},1000)
setInterval(()=>{console.log('setInterval');},1000)
setImmediate(()=>{console.log('setImmediate');})
process.nextTick(()=>{console.log('process.nextTick');})
结果
process.nextTick
setImmediate
setTimeout
setInterval
setInterval
setInterval
setInterval
.
.
.
可以看出来不认识的那个比较快,然后是setImmediate立即执行,然后是setTimeout,最后是setInterval,至于为什么第一个比较快,我猜测可能他可能和promise一样是个微任务,老师说后面时间循环会讲。
global全局对象
据说里面很全,啥都有但打印出来只有一部分,可以去cmd里面输入golbal .然后按两下tab查看里面的东西
JavaScript的模块化
这老师说的非常牛,解决了我多年的困扰,当年大一指针啥的没好好学,以后有机会要恶补数据结构。
js以前是没有模块化的所以很容易出问题比如在同一个目录下创建三个js文件
第一个文件bar.js
var name = 'kabuto'
console.log(name);
第二个文件foo.js
var name = 'ATM'
console.log(name);
第三个文件baz.js
console.log(name);
然后在html里引入这三个文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
<script src="foo.js"></script>
<script src="bar.js"></script>
<script src="baz.js"></script>
打开网页控制台会发现
foo.js:2 ATM
bar.js:2 kabuto
baz.js:1 kabuto
明明没有在baz.js里定义name却可以打印出name,这说明在不同js文件里写代码并重复定义了变量很容易让程序出问题,所以出现了很多模块化js的规则。
第一个介绍规则是commonjs,现在用的貌似都是这个。
定义两个文件一个bar.js一个main.js,在bar.js声明两个变量一个函数,并用exports导出去
const name = 'kabuto'
const age = 18
const hhh = '哈哈哈'
function sayHello(name){
console.log("你好" + name);
}
exports.name = name
exports.age = age
exports.sayHello = sayHello
然后在main.js文件中引用过来,并打印一下
const bar = require('./bar')
console.log(bar.name);
console.log(bar.age);
bar.sayHello('kabuto')
可以得到
kabuto
18
你好kabuto
但如果打印定义了但没有导出的数据
console.log(bar.hhh);
结果
undefined
可以看出来exports导出入才能显示,若直接引用就是未定义
那exports是什么呢我们来打印一下
console.log(exports);
结果
{}
可以看出exports是一个空对象,exports导出的过程就是给一个空对象赋值,然后另一个文件用require将已赋值的exports引入并赋值给bar,那么可以用解构赋值去验证。
const {name,age,sayHello} = require('./bar');
console.log(name);
console.log(age);
sayHello('kabuto')
结果
kabuto
18
你好kabuto
可以看出和上面的结果一样。
exports指向一个空对象,在bar.js里给空对象赋值然后require也指向这个空对象,在空对象发生改变时两个都跟这改变老师举了一个非常通俗易懂的例子来解释
我们重新定义一个对象obj给这个对象来添加两个属性,再定义一个对象info把obj赋值给info,我们改变info中的one属性看看obj会发生什么
const obj = {
one:'一',
two:'二'
}
const info = obj
info.one = '三'
console.log(obj.one);
三
可以看到当我们改变info中的one时obj中的one也发生了变化,这是为什么呢,其实给是电脑里开辟了一份内存空间,这两个对象都指向这个内存空间,当我们通过info修改这个内存空间时,obj也会发生相应的变化。
同理,我们可以通过计时器来修改exports来验证这一理论,
在bar.js中加入一个计时器
const name = 'kabuto'
const age = 18
function sayHello(name){
console.log("你好" + name);
}
exports.name = name
exports.age = age
exports.sayHello = sayHello
setTimeout(()=>{
exports.name = '独角仙'
},1000)
我们在一秒后通过exports将内存空间中的name改成了独角仙,同理我们在main.js中也写一个计时器,在两秒后打印一下name
const bar = require('./bar')
console.log(bar.name);
console.log(bar.age);
bar.sayHello('kabuto')
setTimeout(()=>{
console.log(bar.name);
},2000)
kabuto
18
你好kabuto
独角仙
可以看出两秒后name变成了独角仙验证了刚刚内存空间的说法
但其实模块化导出的本质并不是exports,而是module.exports,node中通过module.exports=exports让这两个指向了一块内存空间,所以改变exports时require和module.exports会一起发生改变,因为他们指向的内存空间发生了改变。
来验证一下在bar.js中
const name = 'kabuto'
const age = 18
function sayHello(name){
console.log("你好" + name);
}
exports.name = name
exports.age = age
exports.sayHello = sayHello
setTimeout(()=>{
exports.name = '独角仙'
},1000)
console.log(module.exports.name + 'm');
setTimeout(()=>{
console.log(module.exports.name + 'm');
},2000)
在main.js中引入bar.js
const bar = require('./bar')
运行
kabutom
独角仙m
可以看出第一次打印的是改变之前的name第二次打印的是改变之后的name,exports改变时module.exports会跟着改变,证明了他们指向同一个内存空间,
那么怎么证明module.exports是是模块化导出的本质呢?很简单,我们只要给module.exports开辟一个新的内存空间,若require的指向也发生改变但exports的指向不变,就证明了module.exports才是模块化导出的核心。
bar.js
const name = 'kabuto'
const age = 18
function sayHello(name){
console.log("你好" + name);
}
exports.name = name
exports.age = age
exports.sayHello = sayHello
module.exports = {
name:'独角仙',
age:'81',
sayHello:function(name){
console.log('1,2,3,骑士踢');
}
}
mian.js
const bar = require('./bar')
console.log(bar.name);
console.log(bar.age);
bar.sayHello('骑士踢')
运行
kabuto+ex
18+ex
你好+ex
undefined
独角仙
81
1,2,3骑士踢
虽然中间不知到为什么会有一个未定义,不过问题不大,我们可以看出,改变module.exprots时,main.js中的 require引入也发生了变化,但exports却没有发生变化,所以module.exprots才是模块化导出的本质,老师最后还出了几个小题目检测对内存空间的理解
在bar.js里设置一个定时器一秒后改变name,两秒后再main.js里打印name,打印的name 是原本的name还是改变之后的name呢。
bar.js
let name = 'kabuto'
const age = 18
function sayHello(name){
console.log("你好" + name);
}
setTimeout(()=>{
name = 'nihao'
},1000)
exports.name = name
exports.age = age
exports.sayHello = sayHello
main.js
const bar = require('./bar')
console.log(bar.name);
console.log(bar.age);
bar.sayHello('骑士踢')
setTimeout(() => {
console.log(bar.name);
}, 2000);
打印
kabuto
18
你好骑士踢
kabuto
可以看出name并没有发生改变,因为在exports.name = name时就已经把name传入内存空间里了,一秒中之后改变的是bar.js中的name不是内存空间中的name,所以两秒之后的打印不会发生变化。
day1结束希望明天继续,吼nana。
day2
工作写静态,下班写node生活实在是太充实了,今天没啥时间只看了一个视频
require的细节
require本质是一个函数,那么require是怎么引入的呢,情况分为3种
情况一
require(x),其中x是一个核心模块比如path和http,这是require会直接返回核心模块并停止查找。
情况二
require(x) x以以./ ../ /(根目录)开头,这种情况,分为三步
第一步:将x当作一个文件在对应目录下查找
1直接查找文件x
2查找x.js
3.x.json
4.x.node
如果没有找到就进行第二步
1.x/index.js
2.x/index.json
3.x/index.node
第三步:都没找到,报错
情况3:直接写个x
如果不是核心模块就去上一层目录的node_modules里找并一直往上找,到根目录找不到就报错,require引入时会运行引入的代码,引入的会先执行,同一个文件多次引入时会缓存只执行一次,引入的顺序遵循深度优先算法
就比如说我按上面的图顺序进行引入敲一下代码验证一下
main.js
const aaa = require('./aaa')
const bbb = require('./bbb')
aaa.js
console.log('aaa');
const ccc = require('./ccc')
bbb.js
console.log('bbb');
const ccc = require('./ccc')
const eee = require('./eee')
ccc.js
console.log('ccc');
const ddd = require('./ddd')
ddd.js
console.log('ddd');
const ddd = require('./eee')
eee.js
console.log('eee');
const eee = require('./eee')
那么输出结果是什么呢,打印一下
PS C:\Users\KABUTO\Desktop\codewhy\node.js\04_javaScript-mosule\02-commonjs3> node .\main.js
aaa
ccc
ddd
eee
bbb
可以看到输出结果是aaa->ccc->ddd->eee->bbb这时因为先引入了aaa再引入了bbb所以先执行aaa,在aaa里有引入了ccc,所以执行,以此内推一直执行到eee,之后再一层一层往回查找一直到main.js发现mian.js里还引入了bbb所以再执行bbb至于bbb中引入的ccc,和eee已经引入过了所以不会继续引入,而且有个细节再require上写console.log是会先运行打印后运行导入的。
中午领导要求加功能晚上继续写
后面到了es6的模块化,也就是平时vue里用的哪些import和export
当我们写html页面时,给页面加一个type = 'module'就可以实现模块化了,Es module是异步的不会阻塞普通的script。
虽然是第三天了,但还是day2,没时间写了看看休息日能不能把这几天的都补上
es6模块化导出的三种方式
第一种,直接导出
export const name = 'kabuto'
第二种,{ }统一导出
export{
}//{}不是个对象
{ }不是一个对象 这里和有commonJs有区别
第三种,导出的时候给对象取别名
export{
name as fName
age as fAge
sayHello as fSayHello
}
常见的三种导入方式
1 improt {} from '路径'
import {name,age,sayHello}//这也不是对象 from '路径'
2. 导出变量之后可以起别名
import {name as wName,age as wAge,sayHello as wSayHello} from '路径'
3. * as foo
import * as foo from '路径'
注意,就是如果导出的时候已近给对象取了别名在使用第二种方式导入时就要使用修改过的别名 而写这里文件必须要写后缀,脚手架里才可能不写。
export和import结合使用
export {sum as barSum} from '路径'
default用法,默认导出,一个模块只能有一个
default export function(){
console.log(1)
}
引入
import '名字' from 路径
平时写项目还是很常用默认暴露然后直接引入的,这个名字可以我们自己取,非常的方便这个方式引入有一个要注意的点,就是不能在if判断里写import,import是解析阶段,不能放在运行阶段里执行,而require的本质是一个函数可以在判断里使用
day3
其实还是第三天,昨天没啥代码,基本都是理论所以写的挺快,上班了,等午休继续写。
在node中支持Es module我们需要进行如下操作
方式一:在package.json中配置type:module (没学)
方式二:文件以.mjs结尾,表示使用的时es module
这里我们来尝试一下
foo.mjs
const name = 'kabuto'
export {name}
mian.mjs
import {name} from './foo.mjs'
console.log(name);
运行
kabuto
可以看出把后缀名改成mjs后就可以正常运行了
commonJs和Es module的交互
commonJs加载Es module
通常情况下不兼容,但是不绝对反正node不行
Es module加载commonJs通常可以
试一试Es module加载commonJs
foo.js
const name = 'kabuto'
exports.name = name;
main.js
import {name} from './foo.js'
console.log(name);
打印一下
kabuto
确实是可以的
好,上面就是模块化的全部东西了,偏理论的东西比较多,光听不动手效果也不是很好,下面就开始将node中的常用内置模块了,现在记得不是很清晰了,正好写一遍笔记巩固一下
常见的内置模块
前面说require导入规则的时候提过一下内置模块,要用的时候必须导入一下,这里我们用的就是require导入,
path模块
path是和路径有关的模块它可以获取到路径也可以做路径的拼接,下面我们来演练一下先引入我们的path模块,然后定义两个路径,我们使用resolve就能把两个路径拼接成一个完整的路径。
const path = require('path')
const basePath = '/User/KABUTO'
const filename = 'abc.txt'
//resolve
const filepath = path.resolve(basePath,filename);
console.log(filepath);
打印
C:\User\KABUTO\abc.txt
可以看到拼接成功了,下面我们来介绍path模块里的其他方法,当然也包括resolve
1.获取路径信息
const filenpath = '/User/KABUTO/abg.txt'
console.log(path.dirname(filenpath)); //获取对应文件夹的name
console.log(path.basename(filenpath));//获取文件的名字
console.log(path.extname(filenpath));//获取文件后缀名
打印一下
/User/KABUTO
abg.txt
.txt
可以看到获取到了相对应的名字,就是单词有点难背。
2.join路径拼接(比较笨)
join可以把两个路径拼接到一起和下面的resolve一样,但是这个方法比较笨不能识别文件前的./之类的路径
const basepath = '../User/why'
const filename = 'abc.txt'
const filepath = path.join(basepath,filename)
console.log(filepath);
打印一下
..\User\why\abc.txt
可以看出来拼接成功了,但它并没有识别出来前面的../可能有些不清晰,但对比一下resolve就可以很明显的看出哪里不一样。
3.resolve路径拼接
resolve会判断拼接的字符串中是否以/或者./或../开头的路径
const basepath = '../User/why'
const filename = 'abc.txt'
const filepath2 = path.resolve(basepath,filename);
console.log(filepath2);
运行一下
C:\Users\KABUTO\Desktop\codewhy\node.js\05_常见的内置模块\User\why\abc.txt
可以看出resolve可以识别路径之前的..并把识别了前面的路径拼接到了路径前面,非常的智能
fs模块
fs是和文件有关的模块它可以获取到文件也可以操作文件,下面我们来演练一下先引入我们的fs模块,然后来操作一下文件
首先创建一个txt文件在里面写入一些东西
abc.txt
hello world
在js文件中读取这个文件的信息有三种方式
第一种:同步操作
const fs = require('fs')
const filepath = "./abc.txt"
const info = fs.statSync(filepath);
console.log('nihao');
console.log(info);
console.log('nihao');
打印一下
PS C:\Users\KABUTO\Desktop\codewhy\node.js\05_常见的内置模块\02_fs> node .\01_fs的三种使用方式.js
nihao
Stats {
dev: 3772190872,
mode: 33206,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
blksize: 4096,
ino: 2251799814976833,
size: 32,
blocks: 0,
atimeMs: 1679109785262.005,
mtimeMs: 1678893991065.0947,
ctimeMs: 1678893991065.0947,
birthtimeMs: 1678892243213.364,
atime: 2023-03-18T03:23:05.262Z,
mtime: 2023-03-15T15:26:31.065Z,
ctime: 2023-03-15T15:26:31.065Z,
birthtime: 2023-03-15T14:57:23.213Z
}
nihao
可以看到同步读取信息阻塞了打印的执行
第二种:异步操作
const fs = require('fs')
const filepath = "./abc.txt"
console.log('nihao');
fs.stat(filepath,(err,info)=>{
if(err){
console.log(err);
return
}
console.log(info);
})
console.log('nihao');
打印一下
nihao
nihao
Stats {
dev: 3772190872,
mode: 33206,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
blksize: 4096,
ino: 2251799814976833,
size: 32,
blocks: 0,
atimeMs: 1679109785262.005,
mtimeMs: 1678893991065.0947,
ctimeMs: 1678893991065.0947,
birthtimeMs: 1678892243213.364,
atime: 2023-03-18T03:23:05.262Z,
mtime: 2023-03-15T15:26:31.065Z,
ctime: 2023-03-15T15:26:31.065Z,
birthtime: 2023-03-15T14:57:23.213Z
}
可以看到异步操作并没有阻塞同步任务的运行,这涉及到js的事件循环后面老师应该会讲。
第三种:promise也是异步不会阻塞,输出同上
console.log('nihao');
fs.promises.stat(filepath).then(info => {
console.log(info);
}).catch(err => {
console.log(err);
})
console.log('nihao');
我们也可以利用文件描述符来获取文件信息
const fs = require('fs');
fs.open("./abc.txt",(err,fd)=>{
if(err){
console.log(err);
return;
}
console.log(fd);
//通过文件描述符去获取文件的信息
fs.fstat(fd,(err,info)=>{
console.log(info);
})
})
打印一下
3
Stats {
dev: 3772190872,
mode: 33206,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
blksize: 4096,
ino: 2251799814976833,
size: 32,
blocks: 0,
atimeMs: 1679109785262.005,
mtimeMs: 1678893991065.0947,
ctimeMs: 1678893991065.0947,
birthtimeMs: 1678892243213.364,
atime: 2023-03-18T03:23:05.262Z,
mtime: 2023-03-15T15:26:31.065Z,
ctime: 2023-03-15T15:26:31.065Z,
birthtime: 2023-03-15T14:57:23.213Z
}
可以看到他的文件描述符是3,我们也根据文件描述符获取到了文件信息
fs模块还可以操作文件的内容,比如如果我们想要在abc.txt里写入内容
const fs = require('fs');
const content = "我不好,很合理"
fs.writeFile('./abc.txt',content,{flag:"a"},err => {
console.log(err);
})
如果输出null代表写入成功了,这里的{flag:"a"}代表不覆盖原有的内容,如果不加原来的内容就会被覆盖掉。
确实加进去了,当然fs也可以读取文件
const fs = require('fs');
const content = "我不好,很合理"
fs.readFile('./abc.txt',{encoding:'utf8'},(err,data) => {
console.log(data);
})
确实也可以读出来这里的UTF-8是控制编码格式的,如果不加可能会乱码
fs模块也可以对文件夹进行操作
利用fs可以新建文件夹
const fs = require('fs')
const path = require('path')
//创建文件夹
const dirname = './nihao';
if(!fs.existsSync(dirname)){
fs.mkdir(dirname,err => {
console.log(err);
});
}
这样如果我们同路径中如果没有这个文件夹node就会帮我们创建一个
可以看到创建成功了
我们还可以读取文件夹里的文件
const fs = require('fs')
const path = require('path')
const dirname = './nihao';
fs.readdir(dirname,(err,files) => {
console.log(files);
})
node 一下
当然如果要想读取文件夹里的文件夹我们可以使用递归,这里我们把读取文件封装成一个函数
function gitFiles(dirname){
fs.readdir(dirname,{withFileTypes:true},(err,files) => {
files.forEach((file)=>{
if(file.isDirectory()){
const filepath = path.resolve(dirname,file.name);
gitFiles(filepath)
}else{
console.log(file.name);
}
})
})
}
gitFiles(dirname)
运行一下
成功获取到啦,太不容易了,递归什么的
我们还能给文件重命名
const fs = require('fs')
fs.rename("./nihao","./hello",err=>{
console.log(err);
})
运行
成功改变了文件夹的名字
events的基础方法
const EventEmitter = require("events")
//1.创建发射器
const emitter = new EventEmitter();
//2.监听某一个事件
//addListener时on的alias简写
emitter.on('click',(args)=>{
console.log('监听到了1的click事件',args);
})
const listener2 = (args)=>{
console.log("监听到了2",args);
}
emitter.on('click',listener2)
//取消监听
emitter.off('click',listener2)
//发出一个事件
emitter.emit("click","kabuto","nihao")
运行一下
成功
day4
讲了一些npm相关的问题
首先我们下载和发布包其实是发布到registry上的
我们通过npm init可以初始化一个npm包,也可以通过npm init -y 直接初始化跳过步骤当我们初始化完成之后会出现package.json文件,这个相信大家并不陌生,写vue项目的时候经常用到,下载了啥都能从里面看到。
{
"name": "06_npmdemo",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": ""
}
我们可以在在scripts中写入"start": "node index.js"这样就可以使用npm start直接运行文件了
非常的方便我们在项目里安装一个axios测试一下
可以看到我们的项目中多了一个node_modules,package.json中的内容也发生了变化
这里也多了一个axios这里的dependencies是无论开发阶段还是生成环境都要用到的包
devDependencies(在package-lock.json里)是生成环境不需要的我们可以看到后面跟了一个版本号,
semver版本规范是X.Y.Z
X是主版本号,当你做了不兼容API修改(可能不兼容以前的版本)
Y是次版本号,当你做了向下兼容的功能新增(新功能增加,但兼容以前的版本)
Z手机修订号:当你做了向下兼容的问题修正(没有新功能修复了bug)
^和~的区别
^是表示x 保持不变Y和Z永远安装最新的版本
~是X和Y保持不变z永远安装最新版本
我们可以通过npm install " "来进行局部安装也可以通过npm install " " -g来进行全局安装,全局安装的一般是类似yarn,webpack这样的包,局部安装的一般则是类似axios这样的包,类似npm的工具还有cnpm和yarn等,这几天状态不是很好,所以听课效率比较差,晚上继续day5的学习。明天应该是封装一个自己的脚手架可能会单独放在一个文章里。
day5
脚手架工具差点给我干放弃了,一开始能听的大差不差,后面真的是离谱,由于是照着敲的没什么思路就直接跳day6了。
day6
今天全是理论,基本没什么代码,只有几道面试题需要敲一下代码,虽然全是理论但非常的重要
进程和线程
可以把进程理解为工厂里的一个车间,线程理解为程序里面运行的车间里的流水线,我们的浏览器一般是多进程,每打开一个新窗口就是一个进程,但javaScript在浏览器中是单线程的,所以任务多的时候可能会卡,这个时候事件循环就非常重要了。
事件循环
事件循环分为浏览器中的事件循环和node中的事件循环,先说浏览器中的事件循环
因为js在浏览器中是单线程的,所以在运行的时候碰到异步任务可能会阻塞,而事件循环可以帮我们解决这个问题,浏览器在运行js的时候会额外开两个队列,宏任务队列和微任务队列,这两个队列用来存放异步任务,如果是同步任务就直接扔到主线程中执行,如果是异步任务,就扔到其他队列里等待,如果达到执行条件再放进主线程,而这两个队列中,微任务队列的优先级又大于宏任务队列所以一些常见的谁先输出的面试题就非常好解决的。
有几个注意点,promise后面直接跟这的算同步任务,.then()后面跟这的才是微任务,await后面跟着的也是同步任务,后面才是微任务。
node中的事件循环
Node.js是单线程的语言,是通过事件循环处理非阻塞I/O操作的。 node中的事件循环主要靠libuv,js代码交给v8解析,v8载传给libuv,libuv再传给操作系统,libuv 里有一个线程池可以拿到异步IO事件轮询然后传给事件循环,所以node中的事件循环多了几个队列,具体记不太清哪几个阶段了反正 同步>process.nextTick()>其他微任务>定时器>IO>setImmediate,但有时有特殊情况就是setImmediate可能会比计数器先输出因为io阻塞。
day7
buffer
buffer用于在内存中存放二进制数据,nodejs不能控制数据传输的时间,若没到发送时间,则数据会存放在Buffer中,直至将数据发送完毕。buffer的初始空间是8kb也就是1024个比特也就是1024x8个比特,总之能存很多字,话不多说我们直接上代码
const message = 'hello'
var buffer = new Buffer(message)
console.log(buffer);
可以看到Buffer后面跟这的两位两位的数字就是buffer非常的工整,但后面会有很多提示我们可以用另一种方式创建buffer来关掉这些提示
const message = 'hello'
var buffer = Buffer.from(message)
console.log(buffer);
可以看到这样就没有提示了,这里我们将hello转成了buffer,这里正好五个数字,所以一个字母对应一个数字。
下面我们来看看buffer的中文编码
const message = "你好"
var buffer = Buffer.from(message)
console.log(buffer);
console.log(buffer.toString());
可以看到 一个中文对应三个数字,我们也可以直接.toString()来把我们的buffer转成中文。
我们可以通过某种方式直接创建一个指定大小的buffer里的值通过buffer.alloc创建方式
const buffer = Buffer.alloc(8);
console.log(buffer);
buffer[0]=88
buffer[1]=0x88
console.log(buffer);
可以看到我们创建完成了并且可以根据索引修改里面的值