第十六章 EventLoop(Browser)
第十六章 任务队列
定时器
定时器作为宏任务,在执行时,会先将定时器任务进行计时,待主线程运行完毕后,立即执行。
setTimeout(() => {
console.log("主任务队列,排列1,运行2");
}, 2000)
setTimeout(() => {
console.log("主任务队列,排列2,运行1");
}, 1000)
Promise.resolve().then(() => {
console.log("微任务队列")
})
console.log("主线程任务");
Promise微任务执行逻辑
Promise主体是主线程任务,Promise.then是微任务,
setTimeout(() => {
console.log("宏任务");
}, 1000);
new Promise(resolve => {
console.log("立即执行,属于主线程任务");
resolve();
}).then(resolve => {
console.log("then属于微任务");
})
DOM渲染逻辑
进行DOM渲染时,默认从上到下执行js代码,
如果将script标签放在头部,且js代码执行时间较长,会给用户造成一种页面有问题的感觉。
实际上执行主线程的时候是这样子的。
所以这就是为什么要将script标签放在body之后的原因。
同步
同步指的是队列顺序下的执行。
同步不等于同时。只是间隔时间比较小,最重要的是同步是有顺序的
let i = 0; //主线程任务
setTimeout(() => {
console.log(++i);
}, 1000)//宏任务队列1 使用主线程i=0,进行操作后,i=1
setTimeout(() => {
console.log(++i);
}, 1000)//宏任务队列2 使用宏任务队列1 i=1,进行操作后i=2
任务轮询
<div class="demo">1%</div>
<style>
.demo {
display: flex;
align-items: center;
justify-content: center;
border: solid 2px #aaa;
height: 50px;
width: 1px;
background: #a44f;
}
</style>
function handle() {
let i = 0;
let div = document.querySelector(".demo");
(function run() {
if (i < 100) {
setTimeout(() => {
++i; //关键在这,即便是执行console.log(++i),i也会在任务队列里进行++i操作
div.innerHTML = i + "%";
div.style.width = i + "px";
run();
}, 10)
}
})()
}
handle()
任务拆分
机器的任务拆分和人相似。
当面对大量计算时,使用拆分效果会更好。
function question_exposed() {
let num = 987654321;
let res = 0;
for (let i = 0; i <= num; i++) {
res += num--
}
console.log(res)
}
question_exposed();
console.log("this is main")
任务拆分并没有本质上减少任务量,只是对于人来说,我们能够知道进度。不过这一点十分重要
let num = 98765;
let res = 0;
function question_exposed() {
for (let i = 0; i <= num; i++) {
if (num <= 0) break;
res += num--
}
if (num > 0) {
console.log(num)
setTimeout(question_exposed)
} else {
console.log(res)
}
}
question_exposed();
console.log("this is main")
Promise微任务处理
有些数据需要在后台进行计算,而前台专注于任务显示。
在后台计算的数据,我们往往需要拿到数据的结果,进行后续的计算。
async function get_res() {
let res = await Promise.resolve().then(() => {
let count = 0;
for (let i = 0; i <= num; i++) {
count += num--;
}
return count;
})
console.log(res);
}
let num = 9890000;
get_res(num);
console.log("main")