-
Notifications
You must be signed in to change notification settings - Fork 193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
45.理解事件循环二(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 执行模型
再简单点可以总结为:
其他
The text was updated successfully, but these errors were encountered: