搞笑     

事件循环 事件循环Event Loop

2022-01-21 04:35搞笑

1.关于java

java是单线程语言,最新的HTML5中提出了Web-Worker,但是Java的核心是单线程。所以所有java版本的“多线程”都是单线程模拟的,所有java多线程都是纸老虎!

2.java事件周期

事件循环是js实现异步的一种方法,也是js的执行机制。

首先,浏览器会逐个执行主任务队列中的所有同步任务,然后等待任务队列查看哪个任务可以执行。

然后把要执行的任务放到主任务队列中,当任务完成后,

等待任务看谁能执行,然后把这个任务放到主任务队列中执行...等等。

这种循环称为事件循环

Js是单线程,js任务要一个一个执行。如果一个任务花费的时间太长,那么下一个任务也必须等待。那么问题来了,如果我们想浏览新闻,但新闻中包含的超清晰图片加载缓慢,我们的网页是否应该一直卡到图片完全显示出来?因此,聪明的程序员将任务分为两类:1)同步任务2)异步任务

图表代表一个事件周期

#1.同步和异步任务分别进入不同的执行场所,同步进入主线程,异步进入Event Table并注册函数。

#2.当指定的事情完成后,事件表将把这个函数移到事件队列中。

#3.当主线程中的任务以空执行时,相应的函数将从事件队列中读取并在主线程中执行。

#4.上述过程会不断重复,这通常被称为事件循环。

主线程执行栈空是什么时候?

js引擎中有一个监控过程,会持续检查主线程执行栈是否为空。一旦是空,就会去事件队列检查是否有函数等待调用。~~~~

所以可以这样看:

1.浏览器线程首先执行同步任务,在途中遇到异步任务时,将其添加到等待任务队列中,然后继续向下执行。

2.所有同步任务执行完毕后,在任务队列中等待,逐个执行所有可执行的微任务。

3.执行完微任务后,先取第一个达到执行条件的宏任务执行,

4.执行结束后,等待任务队列清理并执行所有达到执行条件的微任务,

5.然后执行下一个宏任务。如果宏任务生成微任务或者宏任务生成宏任务,就会被添加到等待任务队列中,然后主线程会先执行所有的微任务,再逐个执行宏任务。

异步任务总是由先达到条件的人来执行,但也存在优先级问题,这取决于任务是宏任务还是微任务;微观任务的优先级高于宏观任务。

3.传动机构

在事件循环中,每个循环操作称为tick,每个tick的任务处理模型比较复杂,但关键步骤如下:

*执行宏任务

*如果在执行过程中遇到微任务,将其添加到微任务的任务队列中

*宏任务执行后,立即执行当前微任务队列中的所有微任务。

*当前宏任务完成后,开始检查渲染,然后GUI线程接管渲染

*渲染后,JS线程继续接管并启动下一个宏任务

一张图片解释道

宏任务:

任务,可以理解为执行栈每次执行的代码都是宏任务。

为了让JS内部任务和DOM任务能够有序执行,浏览器会在一个宏任务执行完之后,下一个宏任务执行之前,重新渲染页面。流程如下:

任务->渲染->任务->;...

微任务:

Microtask可以理解为在当前任务执行后立即执行的任务。也就是说,在当前任务之后、下一个任务之前和渲染之前。

因此,它的响应速度比setTimeout更快,因为不需要等待渲染。也就是说,宏任务执行后,其执行过程中产生的所有微任务都将被执行。

代码块1

setTimeout

});

新承诺{ 0

console . log;

决心;

}).然后

console.log

});

console . log;//2 4 3 1

分析:

settimeout是一个宏任务。虽然它是先执行的,但它被放入宏任务的eventqueue中。向下查看是否有微任务,发现Promise回调函数中的代码是同步输出2

然后,函数将他放入微任务序列。

主代码块输出4

主线流程中所有代码的执行完毕。首先,从微任务队列中取回函数,输出3个微任务全部完成

从宏任务的队列中获取函数。产出1

代码块2

console . log;

setTimeout;

process.nextTick;

})

新承诺{ 0

console . log;

决心;

}).然后

console.log

})

})

process.nextTick;

})

新承诺{ 0

console . log;

决心;

}).然后

console.log

})

setTimeout;

process.nextTick;

})

新承诺{ 0

console . log;

决心;

}).然后

console.log

})

})

1.主代码块输出1

2.宏任务1设置输出

3.微任务1流程

4 .立即执行promise,回调是同步输出7,然后是微任务2

5.宏任务2设置输出

主代码被完全执行

6.执行微任务1,输出6

7.执行微任务2,输出8

所有微任务均已执行

8.执行宏任务1,输出2,

增量任务流程

Promise立即执行回调输出4、微任务、

9.执行微任务输出3和输出5

10.执行宏任务2,输出9,

增量任务流程

Promise立即执行回调输出11、微任务,

11.执行微任务输出10、输出12

代码块3

异步功能async1{

console . log;

等待async2

console . log;

}

异步功能async2{

console . log;

}

console . log;

setTimeout;

}, 0)

async1

新承诺{ 0

console . log;

决心;

}).然后

console . log;

});

console . log;

1.输出“开始”

2 .设置输出宏任务

执行async1输出async1 start,执行async2,输出“async2”。

4.执行async2后,将wait async2后面的代码添加到微任务队列async 1 end’);

5.继续执行,新建Promise,同步输出“promise1”。然后,加入微任务队列,

6.输出端

7.执行当前宏任务后,检查微任务队列的输出async 1 end“promise 2”

8.执行完所有的微任务后,检查宏任务并输出setTimeout

更改上面的代码:

异步功能async1{

console . log;

letp =等待async2

console . log;

console . log;

}

异步功能async2{

console . log;

returnnew Promise= gt;{

决心;

}))

}

console . log;

setTimeout;

}, 0)

async1

新承诺{ 0

console . log;

决心;

}).然后

console . log;

});

console . log;

开始

async1开始

async2

承诺1

目标

承诺2

10

async1结束

定时器

new promise的操作就跟你 new 一个普通函数没区别,所以这一句其实是宏任务,但后面的then是微任务resolved后的promise对象会在这该级别事件队列结束之后才开始执行,及执行与该轮微任务队列中,始于下一级别宏任务之前resolved 的 Promise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。如果出现两个这种微任务,则先出现的会先执行 async 函数中,遇到 await 会跳出当前函数,并让出线程,再将await后面的代码放到 微任务队列中

SegmentFault认为社区应该与文章作者有更多的互动和交流。

-结束-

点击展开全文