从面试题了解事件循环机制:
第一道:
//请写出输出内容
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
第二道:
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
//async2做出如下更改:
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise3');
resolve();
}).then(function() {
console.log('promise4');
});
console.log('script end');
第三道:
async function async1() {
console.log('async1 start');
await async2();
//更改如下:
setTimeout(function() {
console.log('setTimeout1')
},0)
}
async function async2() {
//更改如下:
setTimeout(function() {
console.log('setTimeout2')
},0)
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout3');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
第四道:
async function a1 () {
console.log('a1 start')
await a2()
console.log('a1 end')
}
async function a2 () {
console.log('a2')
}
console.log('script start')
setTimeout(() => {
console.log('setTimeout')
}, 0)
Promise.resolve().then(() => {
console.log('promise1')
})
a1()
let promise2 = new Promise((resolve) => {
resolve('promise2.then')
console.log('promise2')
})
promise2.then((res) => {
console.log(res)
Promise.resolve().then(() => {
console.log('promise3')
})
})
console.log('script end')
第五道:
setTimeout(function(){console.log(1)},0);
new Promise(function(resolve,reject){
console.log(2);
setTimeout(function(){resolve()},0)
}).then(function(){console.log(3)
}).then(function(){console.log(4)});
process.nextTick(function(){console.log(5)});
console.log(6);
如果不太理解其中所蕴含的道理,点击下:体现事件循环机制过程在线网站
如果能正确答出上面题的输出内容,并能给予背后原理的解释,那证明读者对于JS中事件循环机制了解得挺深入的哦~
之前小编对于JS中事件循环机制了解也是模棱两可,近来对此部分进行了进一步的学习,先以一张图来说明学习成果:
想要了解JS中的事件循环机制,咱们需要了解如下内容:
浏览器是多进程的,JS是单线程的。浏览器除了JS引擎之外,还有Web APIs线程、GUI线程等, JS引擎在执行过程中,如果遇到相关的事件(DOM操作、AJAX请求、滚轮事件、鼠标点击事件、setTimeout等),并不会因此阻塞,它会将这些事件移交给Web APIs线程处理,而自己接着往下进行。
setTimeout:设置的时间是最小延迟时间,并不是确切的等待时间,实际上最小延迟>=4ms,小于4ms的被当做4ms
Web APIs:按照一定的规则将这些事件放入一个任务队列(Callback queue,也叫task queue)
任务队列:在HTML标准定义中,任务队列的数据结构不是队列,而是Set集合
说明:
1、JS线程负责处理JS代码,当遇到一些异步操作的时候,则将这些异步事件移交给Web APIs处理,自己则继续往下执行
2、Web APIs线程将接收到的事件按照一定的规则添加到任务队列中,宏事件添加到宏任务队列中,微事件添加到微任务队列中
3、JS线程处理完当前的所有任务以后(执行栈为空),它会先去微任务队列中获取事件,并将微任务队列中按照先进先执行的顺序一件件执行完毕,直到微任务队列为空后,再去宏任务队列中取出一个事件执行
(每次取完一个宏任务队列中的事件执行完毕后,都先检查微任务队列)
4、然后不断循环第三步。
在这里,小编第一次也并没有理解async/await关键字的作用,在第二遍学习的时候理解了,请看如下示例:
源代码:
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
其实,根据await关键字的作用,会将后面的内容包装成promise,然后应该是如下模样:
async function async1(){
console.log('async1 start')
new promise((reslove)=>{
console.log('async2')
}).then(()=>{
console.log('async1 end')
})
}
基本上在理解了如上相关内容后,对于JS中异步机制以及相关面试题有了深入的理解。
如下为开头面试题答案:
第一道:
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
第二道:
script start
async1 start
promise1
promise3
script end
promise2
async1 end
promise4
setTimeout
第三道:
script start
async1 start
promise1
script end
promise2
setTimeout3
setTimeout2
setTimeout1
第四道:
script start
a1 start
a2
promise2
script end
promise1
a1 end
promise2.then
promise3
setTimeout
第五道:
//输出的是 2 6 5 1 3 4
//区别在于promise的构造中,没有同步的resolve
,因此promise.then在当前的执行队列中是不存在的,
只有promise从pending转移到resolve,才会有then方法,而这个resolve是在一个setTimout时间中完成的,因此3,4最后输出。
巨人肩膀:
谈谈Event Loop中的Job queue
事件循环(event loop)以及异步执行顺序