标签:tick dom 不同的 流程 oop cti script info RKE
总结
setImmediate
等等,执行都是有共同点的,有兴趣的同学可以自行了解。JS为什么是单线程的
new Worker(xxx.js)
在JavaScript中创建多个线程。但是子线程完全受主线程控制,且不得操作DOM。所以JavaScript还是单线程的。在最新的HTML5中提出了Web-Worker,但javascript是单线程这一核心仍未改变。所以一切javascript版的"多线程"都是用单线程模拟出来的。javascript的同步和异步
js为什么需要异步
js单线程又是如何实现异步的呢
JS的事件循环(eventloop)(运行机制)是怎么运作的
JavaScript中的宏任务和微任务
宏任务(macro-task):整体代码script、setTimeout、setInterval、setImmediate
微任务(micro-task):Promise、process.nextTick
宏任务和微任务是对JavaScript异步任务再次细分。异步事件队列分为宏任务事件队列和微任务事件队列。
4.
同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入事件列表并注册回调函数。
当异步任务执行结束后,判断该异步任务是宏任务还是微任务,将宏任务的回调函数添加宏任务事件队列,将微任务的回调函数添加到微任务事件队列。
主线程内的任务执行完毕后。
代码练习:
/*
以下这段代码的执行结果是什么?
如果依照:js是按照语句出现的顺序执行这个理念,
那么代码执行的结果应该是:
//"定时器开始啦"
//"马上执行for循环啦"
//"执行then函数啦"
//"代码执行结束"
但结果并不是这样的,得到的结果是:
//"马上执行for循环啦"
//"代码执行结束"
//"执行then函数啦"
//"定时器开始啦"
*/
setTimeout(function(){
console.log(‘定时器开始啦‘)
});
new Promise(function(resolve){
console.log(‘马上执行for循环啦‘);
for(var i = 0; i < 10000; i++){
i == 99 && resolve();
}
}).then(function(){
console.log(‘执行then函数啦‘)
});
console.log(‘代码执行结束‘);
let data = [];
$.ajax({
url:www.javascript.com,
data:data,
success:() => {
console.log(‘发送成功!‘);
}
})
console.log(‘代码执行结束‘);
复制代码
上面是一段简易的`ajax`请求代码:
//- ajax进入Event Table,注册回调函数`success`。
//- 执行`console.log(‘代码执行结束‘)`。
//- ajax事件完成,回调函数`success`进入Event Queue。
//- 主线程从Event Queue读取回调函数`success`并执行。
setTimeout(function() {
console.log(‘setTimeout‘);
})
new Promise(function(resolve) {
console.log(‘promise‘);
}).then(function() {
console.log(‘then‘);
})
console.log(‘console‘);
//这段代码作为宏任务,进入主线程。
//先遇到setTimeout,那么将其回调函数注册后分发到宏任务Event Queue。(注册过程与上同,下文不再描述)
//接下来遇到了Promise,new Promise立即执行,then函数分发到微任务Event Queue。
//遇到console.log(),立即执行。
//好啦,整体代码script作为第一个宏任务执行结束,看看有哪些微任务?我们发现了then在微任务Event Queue里面,执行。
//ok,第一轮事件循环结束了,我们开始第二轮循环,当然要从宏任务Event Queue开始。我们发现了宏任务Event Queue中setTimeout对应的回调函数,立即执行。
//结束。
console.log(‘1‘);
setTimeout(function() {
console.log(‘2‘);
process.nextTick(function() {
console.log(‘3‘);
})
new Promise(function(resolve) {
console.log(‘4‘);
resolve();
}).then(function() {
console.log(‘5‘)
})
})
process.nextTick(function() {
console.log(‘6‘);
})
new Promise(function(resolve) {
console.log(‘7‘);
resolve();
}).then(function() {
console.log(‘8‘)
})
setTimeout(function() {
console.log(‘9‘);
process.nextTick(function() {
console.log(‘10‘);
})
new Promise(function(resolve) {
console.log(‘11‘);
resolve();
}).then(function() {
console.log(‘12‘)
})
})
// 第一轮事件循环流程分析如下:
// 整体script作为第一个宏任务进入主线程,
// 遇到console.log,输出1。
// 遇到setTimeout,其回调函数被分发到宏任务Event Queue中。我们暂且记为setTimeout1。
// 遇到process.nextTick(),其回调函数被分发到微任务Event Queue中。我们记为process1。
// 遇到Promise,new Promise直接执行,输出7。then被分发到微任务Event Queue中。我们记为then1。
// 又遇到了setTimeout,其回调函数被分发到宏任务Event Queue中,我们记为setTimeout2。
// 宏任务Event Queue 微任务Event Queue
// setTimeout1 process1
// setTimeout2 then1
// 上表是第一轮事件循环宏任务结束时各Event Queue的情况,此时已经输出了1和7。
// 我们发现了process1和then1两个微任务。
// 执行process1,输出6。
// 执行then1,输出8。
// 好了,第一轮事件循环正式结束,这一轮的结果是输出1,7,6,8。那么第二轮事件循环从setTimeout1宏任务开始:
// 首先输出2。接下来遇到了process.nextTick(),同样将其分发到微任务Event Queue中,记为process2。new Promise立即执行输出4,then也分发到微任务Event Queue中,记为then2。
// 宏任务Event Queue 微任务Event Queue
// setTimeout2 process2
// then2
// 第二轮事件循环宏任务结束,我们发现有process2和then2两个微任务可以执行。
// 输出3。
// 输出5。
// 第二轮事件循环结束,第二轮输出2,4,3,5。
// 第三轮事件循环开始,此时只剩setTimeout2了,执行。
// 直接输出9。
// 将process.nextTick()分发到微任务Event Queue中。记为process3。
// 直接执行new Promise,输出11。
// 将then分发到微任务Event Queue中,记为then3。
// 宏任务Event Queue 微任务Event Queue
// process3
// then3
// 第三轮事件循环宏任务执行结束,执行两个微任务process3和then3。
// 输出10。
// 输出12。
// 第三轮事件循环结束,第三轮输出9,11,10,12。
// 整段代码,共进行了三次事件循环,完整的输出为1,7,6,8,2,4,3,5,9,11,10,12。
// (请注意,node环境下的事件监听依赖libuv与前端环境不完全相同,输出顺序可能会有误差)
标签:tick dom 不同的 流程 oop cti script info RKE
原文地址:https://www.cnblogs.com/ycyc123/p/14322646.html