JS事件循环

上周写了篇关于setTimeout的文章,其实也就牵扯到了js的运行机制。所以,这周就来谈谈javascript的运行机制吧。

那就先问个问题吧?。

为什么JavaScript是单线程的?

还是我来回答吧:

单线程意思就是说同一个时间只能做一件事。那这样的话效率不是很低?也没有啦,其实javascript的单线程特点是跟他的用途有关的。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。假如不是单线程的话,在一个线程当我们在给某个DOM节点增加内容的时候,另一个线程正在删除这个DOM节点的内容,那还得了,那不是乱套了吗。所以javascript只能是单线程。

虽然javascript是单线程,但是javascript中有同步和异步的概念,解决了js阻塞的问题。

同步和异步:

一.同步:

如果在一个函数返回的时候,调用者就能够得到预期结果(即拿到了预期的返回值或者看到了预期的效果),那么这个函数就是同步的。

用代码解释一下:

console.log('Hello');
复制代码

如果在函数返回时,就看到了预期的效果:在控制台打印了Hello

二.异步:

如果在函数返回的时候,调用者还不能够得到预期结果,而是需要在将来通过一定的手段得到,那么这个函数就是异步的。

代码解释:

fs.readFile('test.txt', 'utf8', function(err, data) {
    console.log(data);
});
复制代码

在上面的代码中,我们希望通过fs.readFile函数读取文件foo.txt中的内容,并打印出来。但是在fs.readFile函数返回时,我们期望的结果并不会发生,而是要等到文件全部读取完成之后。如果文件很大的话可能要很长时间。

小总结:
  1. 同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为。

  2. 异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作。而,异步方法通常会在另外一个线程中,“真实”地执行着。整个过程,不会阻碍调用者的工作。

javascript就可以进行同步任务和异步任务。把读文件这种操作,ajax请求这些需要耗时的任务放到任务队列中,我还是能够一步步的继续下面的任务。所以啊,javascript还是可以很6。那么异步任务里面只是放要进行异步操作的任务吗,里面会发生啥呢?

任务队列:

上面说过了javascript里面的任务有两种,同步任务和异步任务。

同步任务是指:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。

异步任务指的是,不进入主线程、而进入"任务队列"的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

先看个小栗子吧:

console.log("a");
setTimeout(function () {
    console.log("b");
},0);
console.log("c");

//a
//c
//b
复制代码

js中代码从上往下执行,执行第一行代码的时候控制台输出a,执行到第二行代码的时候遇到了setTimeout函数,因为setTimeout函数是个异步函数,所以,浏览器会记住这个事件,添加到时间表中,之后把这个事件的回调函数入栈到任务队列中。而此时主线程程序继续往下运行,到了第五行:console.log("c"),执行这条,控制台输出c。这时候主线程空了,他会到任务队列里面去查找是否有可以执行的任务,有的话直接拿出来执行,没有的话会一直去询问,等到有可以执行的。

为了更好的说明任务队列和事件循环,先看一张图。?

这张图片里面已经画出了js的事件循环的流程了。 流程:

  1. 所有同步任务都在主线程上执行,形成一个执行栈。
  2. 当主线程中的执行栈为空时,检查事件队列是否为空,如果为空,则继续检查;如不为空,则执行3;
  3. 取出任务队列的首部,压入执行栈;
  4. 执行任务;
  5. 检查执行栈,如果执行栈为空,则跳回第 2 步;如不为空,则继续检查;

Event Loop:

事件循环其实就是入栈出栈的循环。上面例子中说到了setTimeout,那setInterval呢,Promise呢等等等等,有很多异步的函数。但是这些异步任务有分宏任务(macro-task)和微任务(micro-task):

macro-task包括: setTimeout, setInterval, setImmediate, I/O, UI rendering。

micro-task包括:process.nextTick, Promises, Object.observe, MutationObserver。

每一次Event Loop触发时:

  1. 执行完主执行线程中的任务。
  2. 取出micro-task中任务执行直到清空。
  3. 取出macro-task中一个任务执行。
  4. 取出micro-task中任务执行直到清空。
  5. 重复3和4。
其实promise的then和catch才是microtask,本身的内部代码不是。

注意:

  1. 在浏览器浏览器和node中的执行不一样。

  2. 任务队列里面是“先入先出”的。

那来个小栗子测试一下你是不是已经完全理解啦:
console.log('global')

for (var i = 1;i <= 5;i ++) {
  setTimeout(function() {
    console.log(i)
  },i*1000)
  console.log(i)
}

new Promise(function (resolve) {
  console.log('promise1')
  resolve()
 }).then(function () {
  console.log('then1')
})

setTimeout(function () {
  console.log('timeout2')
  new Promise(function (resolve) {
    console.log('timeout2_promise')
    resolve()
  }).then(function () {
    console.log('timeout2_then')
  })
}, 1000)
复制代码

控制台输出:

这个博客能够非常好的加深理解: 深入理解 JavaScript 事件循环(一)— event loop

总结:

这里主要是讲了在浏览器端js事件循环。这篇文章可以帮助更好的理解node和浏览器环境下不同的事件循环:浏览器和Node不同的事件循环(Event Loop)

JavaScript事件循环JavaScript中用于处理异步操作的机制。由于JavaScript是单线程的,它无法同时执行多个任务。为了处理异步任务,JavaScript引入了事件循环机制。 事件循环主要由以下几个组成部分: 1. 调用堆栈(Call Stack):用于存储函数调用的记录。当函数被调用时,会将其压入调用堆栈中,当函数执行完毕后,会从调用堆栈中弹出。 2. 任务队列(Task Queue):用于存储待处理的异步任务。当异步任务完成时,会被添加到任务队列中。 3. 事件循环(Event Loop):负责监听调用堆栈和任务队列的状态,当调用堆栈为空时,会从任务队列中取出任务并执行。 事件循环的工作流程如下: 1. JavaScript引擎执行同步任务,并将异步任务添加到任务队列中。 2. 当调用堆栈为空时,事件循环会从任务队列中取出一个任务。 3. 取出的任务会被压入调用堆栈中执行。 4. 执行完毕后,调用堆栈为空,事件循环继续从任务队列中取出任务执行。 这样循环执行,实现了异步任务的处理。 相关问题: 1. 什么是异步任务?为什么需要处理异步任务? 2. JavaScript如何处理异常? 3. JavaScript中的回调函数是什么?如何使用回调函数处理异步任务? 4. 什么是Promise?如何使用Promise处理异步任务? 5. JavaScript中的定时器有哪些?它们是如何工作的? 6. 什么是事件驱动编程?如何在JavaScript中使用事件驱动编程? 7. JavaScript中的Event Loop与浏览器的渲染机制有什么关系?<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [详解JavaScript事件循环机制](https://download.csdn.net/download/weixin_38694006/13608655)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [浏览器显示数据库中数据的条形图柱状图 前后端分离vue.js+spring boot 计算机软件工程课程设计毕业设计 ...](https://download.csdn.net/download/Amzmks/88275824)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值