likes
comments
collection
share

几分钟拿捏面试必考点——JS事件循环

作者站长头像
站长
· 阅读数 60

前言

js为单线程,即v8在执行js的过程中,只有一个线程会工作,可以节约性能。

同步代码和异步代码

  • 同步代码:不耗时执行的代码;
  • 异步代码:需要耗时执行的

微任务和宏任务

  • 微任务:promise.then(),process.nextTick(),MutationOvserver()
  • 宏任务:script,setTimeout,setInterval,setImmediate,I/O,UI-rendering

进程和线程

  • 进程:cpu运行指令和保存上下文所需的时间
  • 线程:运行一段指令所需的时间

正文

首先介绍一下事件循环的执行步骤,再通过三个实例来实操

事件循环执行步骤:

从上往下执行:

  1. 执行同步代码(这属于是同步宏任务);
  2. 如果有异步代码将其压入宏任务队列中;
  3. 如果有微任务将其压入微任务队列中;
  4. 同步代码执行完毕后;
  5. 将微任务队列出队,依次执行所有的微任务
  6. 微任务执行完毕,如果有需要就会渲染页面;
  7. 将宏任务队列出队,执行异步宏任务,也是开启下一次事件循环。

实例一

console.log(1);
new Promise((reslove, reject) => {
  console.log(2);
  reslove();
}).then(() => {
  console.log(3);
}).then(() => {
    console.log(4);
});

setTimeout(() => {
  console.log(5);
})

console.log(6);

这里我用画图的形式来分析该事件循环结果: 几分钟拿捏面试必考点——JS事件循环

所以结果为:

几分钟拿捏面试必考点——JS事件循环

实例二

console.log(1);
new Promise((resolve, reject) => {
  console.log(2);
  resolve()
})
.then(() => {
  console.log(3);
  setTimeout(() => {
    console.log(4);
  }, 0)
})
setTimeout(() => {
  console.log(5);
  setTimeout(() => {
    console.log(6);
  }, 0)
}, 0)
console.log(7);

几分钟拿捏面试必考点——JS事件循环

结果:

几分钟拿捏面试必考点——JS事件循环

实例三

先介绍一下关于asyncawait的知识点:

let data = null;

function getData() {
    setTimeout(() => {
        data = [1, 2, 3];
    }, 1000);
}

function another() {
    console.log(data);
}

getData();
another();

几分钟拿捏面试必考点——JS事件循环

上面的代码,执行结果为null,因为setTimeout为异步的,所以执行函数getData时会被挂起,先执行函数another,那么怎么才可以让结果为[1, 2, 3]呢?

  • 之前我们介绍过promise,这里我们可以通过promise去实现:
 let data = null;

function getData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            data = [1, 2, 3];
            resolve();
        }, 1000);
    });
}

function another() {
    console.log(data);
}

getData().then(() =>  {
    another();
});

几分钟拿捏面试必考点——JS事件循环

我们也可以使用async实现,同样时要返回一个promise对象,但是不用通过then,而是通过await

let data = null;

function getData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            data = [1, 2, 3];
            resolve();
        }, 1000);
    });
}

function another() {
    console.log(data);
}

async function foo() {
    await getData();
    another();
}
foo();

几分钟拿捏面试必考点——JS事件循环

通过上面的代码可以知道函数前面有async时,函数里面会先执行await后面的代码,还有一个注意点!!! await 执行后会将后续的代码阻塞进微任务队列

给出最后一个例子

console.log('script start');

async function async1() {
  await async2();// await 会将后续的代码阻塞进微任务队列
  console.log('async1 end');
}
async function async2() {
  console.log('async2 end');
}
async1();
setTimeout(function() {
  console.log('setTimeout');
}, 0);
new Promise(function(resolve, reject) {
  console.log('promise');
  resolve()
})
.then(() => {
  console.log('then1');
})
.then(() => {
  console.log('then2');
})
console.log('script end');

几分钟拿捏面试必考点——JS事件循环

几分钟拿捏面试必考点——JS事件循环

结语

几分钟拿捏面试必考点——JS事件循环

转载自:https://juejin.cn/post/7379818614361931786
评论
请登录