Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign up45.理解事件循环二(macrotask和microtask) #48
Comments
|
mark |
|
包裹在一个 script 标签中的js代码也是一个 task,意思就是这些代码会进入事件循环,那为什么会产生阻塞呢?包裹在一个 script 标签中的js代码是指哪些代码? |
<script>
for(var i=0,l=10000;i<l;i++){
....
}
</script>这就是在一个 |
|
index.html中的代码 <script type="text/javascript">
for(var i = 0; i < 10000; i++) {
if(i == 9999) {
console.log('a');
}
}
</script>
<script type="text/javascript" src="main.js"></script>main.js中的代码 console.log('b');script中的代码进入事件循环,那通过src引入的代码就会先执行,那为什么还是会先输出a,再输出b? |
|
上面 script 标签中的代码不是异步执行的 确切的说应该是 script 中的异步代码会进入事件循环等待执行 |
|
哦哦,感谢解答 |
|
mark |
|
mark |
|
你好 我想问假如是http.get fs.readfile的回调算是macrotask吗?还是应该是microtask?(因为想了一下假如代码是这样的 |
|
@authhwang |
|
@ccforward |
|
你的例子中 |
|
@ccforward |
|
@ccforward 你好,有段代码:
不知道自己理解的错误点在哪里,希望指正 PS: 正确的输出结果 1, 2, 3, 5, 4 |
|
@Arweil 建议你看这个 https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/ 看完就大概懂了 然后我在别的地方看到是promise队列的处理then会比事件队列的处理快些 优先级高 不过忘了在哪里看了... |
|
@Arweil (function test() {
setTimeout(function () {
console.log(4)
}, 0);
new Promise(function executor (resolve) {
console.log(1);
for(var i = 0; i < 10000; i++) {
i == 9999 && resolve();
}
console.log(2);
}).then(function() {
console.log(5);
});
console.log(3);
})()我的理解是应该把 script 标签内的代码块 作为一整个 macro-task ,先输出5后输出4。 整个自执行函数是同步操作的,但是你再去写一个自执行函数放入另一个 script 标签内,像这样 <script>
(function test() {
setTimeout(function () {
console.log(4)
}, 0);
new Promise(function executor (resolve) {
console.log(1);
for(var i = 0; i < 10000; i++) {
i == 9999 && resolve();
}
console.log(2);
}).then(function() {
console.log(5);
});
console.log(3);
})()
</script>
<script>
(function test2() {
setTimeout(function () {
console.log(42)
}, 0);
new Promise(function executor (resolve) {
console.log(12);
for(var i = 0; i < 10000; i++) {
i == 9999 && resolve();
}
console.log(22);
}).then(function() {
console.log(52);
});
console.log(32);
})()
</script>执行结果如下:
两个 script 标签的整个执行过程是一个 main thread ,但并不意味着先执行第一个script标签后再执行第二个,因为两个script标签中的 不知道这样解释你会不会明白,我也是看了好多资料后自己的理解。 PS: 你截图里的代码配色不错啊 什么编辑器? 什么主题? |
|
@ccforward @authhwang 感谢回答!编辑器用的sublime text 3 PS:想直接给你传图片,死活传不上去。。。 |
|
@ccforward <script>
new Promise(function executor (resolve) {
console.log(1);
for(var i = 0; i < 10000; i++) {
i == 9999 && resolve();
}
console.log(2);
}).then(function() {
console.log(5);
});
console.log(3);
</script> |
|
@helios741 promise里面构造executor的时候内部是同步执行的。异步的是resolve这种结果的回调 |
|
@Aaaaaaaty 嗯嗯,理解了,thanks |
|
@helios741 客气哈哈 |
|
@junfeisu 这个地方主要是 具体到你的这个例子: process.nextTick(() => {
console.log('nextTick1')
})
process.nextTick(() => {
console.log('nextTick2')
})
setImmediate(() => {
console.log('setImmediate1')
process.nextTick(() => {
console.log('插入')
})
})
setImmediate(() => {
console.log('setImmediate2')
})
console.log('正常执行')在执行第一个 因此最后执行输出的内容应该是: 正常执行
nextTick1
nextTick2
setImmediate1
setImmediate2
插入 |
|
谁能解释下面的现象: <script>
new Promise((resolve, reject)=>{
resolve();
console.log(2);
}).then(()=>{
console.log(3);
});
</script>
<script>
new Promise((resolve, reject)=>{
resolve();
console.log(22);
}).then(()=>{
console.log(33);
});
</script>
2, 3, 22, 33同个标签: <script>
new Promise((resolve, reject)=>{
resolve();
console.log(2);
}).then(()=>{
console.log(3);
});
new Promise((resolve, reject)=>{
resolve();
console.log(22);
}).then(()=>{
console.log(33);
});
</script>
2, 22, 3, 33 |
|
可以这样理解 会优先执行一个 macrotask |
|
@ccforward 感谢回答 |
|
macrotasks: setTimeout ,setInterval, setImmediate,requestAnimationFrame,I/O ,UI渲染 |
|
关于这个,推荐读下国外大神的 Tasks, microtasks, queues and schedules |
|
@zhuanyongxigua 这个应该是作者自己归类的。不过我对 setInterval 的归类持有保留态度。之前看到一个前端 promise 库就是用 setInterval 来模拟实现的。 |



关于 macrotask 和 microtask
上一篇 理解事件循环一(浅析) 用例子简单理解了下 macrotask 和 microtask
这里再详细的总结下两者的区别和使用
简介
一个事件循环(EventLoop)中会有一个正在执行的任务(Task),而这个任务就是从 macrotask 队列中来的。在whatwg规范中有 queue 就是任务队列。当这个 macrotask 执行结束后所有可用的 microtask 将会在同一个事件循环中执行,当这些 microtask 执行结束后还能继续添加 microtask 一直到真个 microtask 队列执行结束。
怎么用
基本来说,当我们想以同步的方式来处理异步任务时候就用 microtask(比如我们需要直接在某段代码后就去执行某个任务,就像Promise一样)。
其他情况就直接用 macrotask。
两者的具体实现
从规范中理解
whatwg规范:https://html.spec.whatwg.org/multipage/webappapis.html#task-queue
再来回顾下事件循环如何执行一个任务的流程
当执行栈(call stack)为空的时候,开始依次执行:
上面就算是一个简单的 event-loop 执行模型
再简单点可以总结为:
其他