node深入学习(1) eventloop

多线程

优点:同时处理多个请求,适合cpu密集型运算
缺点:如果多个线程操作同一个资源得上锁。多线程并不是一起去干一些事情,而是靠切换上下文(浪费一些性能)

单线程

node的主线程是单线程,不需要开启多个线程,节省资源,不适合做大量的cpu操作。但是node提供了开启子进程,可以将比较大的操作放入子进程去运行。

同步异步和阻塞非阻塞

阻塞非阻塞是相对于操作方的,操作放调用了同步方法,这时候就会阻塞。同步异步是相对于调用的方法。比如调用readFile就是异步的。
异步非阻塞:调用异步的方法,操作方不会被阻塞。

event loop

因为node的主线程是单线程,所以node也实现了自己的event loop。
在这里插入图片描述

  • 1 代码会交给v8引擎进行处理
  • 2 代码中可能会调用nodeApi,node会交给libuv库处理
  • 3 libuv通过阻塞i/o和多线程实现了异步io。
  • 4 通过事件驱动的方式,将结果放入事件队列中,最终交给我们的应用。

node使用

默认执行一个文件的时候,在命令行运行node index.js文件的时候,他会把整个文件当成一个模块,默认把this修改了。
在这里插入图片描述
在全局下指向的就是global。

node新增的全局属性

  • buffer node中的二进制对象(最早的时候浏览器不能直接读写文件)
  • process 进程
    process中的一些属性:
  1. platform 当前执行环境的平台(如window(win32),mac(darwin))
  2. chidir,以更改当前工作的目录
  3. env 执行代码的时候可以传入一些环境变量
  4. argv 执行代码的时候可以传入的参数
    在这里插入图片描述
    可以通过传入参数获取。第一二个值是固定的,
    [执行node所在的exe文件,当前的执行文件,…其他参数],用户脚手架启动项目的时候传入一些参数,然后在配置文件中获取这些值。
    解析可以用到commander库(命令行管家)
    在这里插入图片描述
  5. nextTick
    下面祥讲
  6. cwd (current working directory)当前工作的目录,比如webpack会自动擦护照运行webpack的目录下查找webpack.config.js文件。
  • __dirname(当前执行时的目录,绝对路劲) __filename(当前执行时的文件的绝对路劲)
    在这里插入图片描述
  • setImmediate

nextTick与node的eventloop

node中自己实现的,不属于node的eventloop。优先级比Promise更高。nextTick算是微任务,他是当前栈中同步代码执行完毕后立即执行的。因为Node里也有一些异步操作,所以node实现了自己的eventLoop。
而node中的异步队列不比浏览器,node有很多类型的宏任务队列。
在这里插入图片描述
这是官网的案例。
在这里插入图片描述

一共有六种。
  • 第一种是setTImeout等到时间就放入这个队列。
    第二种就是一些回调函数,还有第四种io任务非常多,导致只能下一个循环执行,就会放入这里。
    第三种是内部使用的
    第四种是与io相关的回调 (poll, 比如readFIle)。
    第五种是setImmediate的回调函数
    第六种是一些关闭的回调函数。
    我们重点需要关注第一种,第四种,第五种。
    poll主要是放Io的回调,必须对文件的读写这些readFile等。
    第五种check放一些setImmediate的回调。
  • 代码是从上往下执行的,从第一种走到第六种,走完之后继续走,是个死循环。
  • 但是有个问题,比如setTimeout按道理是在setImmediate前执行,但是有时候会setImmediate先执行。是因为当前默认执行主栈代码,主栈代码执行完毕后要执行定时器,但是定时器可能还没到时间,所以就先往下走,所以setImmediate可能会先执行。
    在这里插入图片描述

在这里插入图片描述
有个特殊情况。就是在这里插入图片描述

当执行io操作的时候,如上,主栈执行完代码之后,会走eventloop,此时同步代码没有setTimeout等,会直接走到第四种,poll,poll中有readFile这个io操作已经完成好的的回调,放在了poll,然后执行回调函数,检查到了setTImeout和setImmediate,分别放入timer队列,和check队列。接着执行完毕后会检查check队列,因为刚才已经放入一个了,所以会立马执行。然后等待setTimeout执行完之后再回到第一种往下执行,所以poll队列的特点是执行完当前队列会先检查有没有check队列的要执行,有的话会先执行第五个队列check的东西。
在这里插入图片描述
所以会出现这种情况。等待完毕后会往回去执行第一个timer队列里面的东西。

  • 浏览器的特点是,先执行栈中代码,清空后为执行微任务,然后渲染页面,再从宏任务队列中取出一个来执行。
  • node是先执行栈代码,执行完毕后,清空当前的微任务队列,会进入事件环中(evetloop),拿出一个来执行,执行完毕后再次清空当前微任务队列。(以前是一个队列! 清空完,再清空微任务,现在是一个执行完,就清空微任务,为的就是跟浏览器表现一致)

global的其他重要属性

global上可以直接访问的属性叫全局属性,而requrei,exports,moudel也可以直接访问,但是不在global。因为每个文件都是一个模块,就好比自执行函数。如

(function(rqeuire, exports, module){})(require,exports,module)

他是作为入参传入,然后在这个模块就可以使用这些。而global上没有。

模块化

为什么要有模块化?

  • 一开始是为了解决命名冲突问题
    1. 最开始是用对象,单例模式,但是不能完全解决这些问题
    2. 然后就是自执行函数,配合文件拆问的方式。但是会有请求问题,依赖问题,(amd cmd)。所以才有define([‘jqury’,‘vue’],()=>{})这种前置依赖,后来也逐渐被淘汰。
    3. umd,兼容amd+cmd+commonjs,但是不支持esmodule
    4. commonjs规范(一个文件就是一个模块,使用就用require,导出就module.exports,他只是一个规范) esmoudle(es的规范,使用就是import from ,到处就是export)
    5. commonjs是基于文件的读写的,是同步的,而且不能在编译时确定,只有在运行的时候才会报错。)
    6. esmodule支持静态编译,(正常每次import一个模块,会发请求,是异步操作,但现在都是靠webpack编译,不会发请求,而是编译成require这些。)
    7. 这也是为什么import不能在if里面编写。import是静态导入,因为总不能在if(true)import 'xx’就去请求,卡在这里,只能放在顶部,这样webpack就会去编译,而放入条件判断中,因为条件判断必须要动态执行才知道结果,所以不可以这样。但是commonjs可以。因为require是同步的,后面es7又出了一个import()就可以在if里面编写。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coderlin_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值