关于JS同步与异步知识(亲测总结):
1.首先明确:JS是单线程.
2.任务分为同步和异步, 异步又细分为宏任务和微任务.
3.JS(单)线程首先执行同步代码(期间如果遇到死循环则所有异步任务将不会被执行),
期间遇到的所有宏任务和微任务分别放入宏任务和微任务两个不同队列中等待执行;
待执行所有同步代码后,JS线程优先从微任务队列调入执行微任务;
所有微任务执行完成后,才开始调入宏任务队列执行第一个宏任务;
如果这个宏任务代码体中含有新建微任务,放入队列,待这个宏任务所有代码体执行完成后(此时宏任务作用域内的代码体视为同步代码),
后续待执行的宏任务先往后站,优先执行这些新建的微任务.也就是说,宏任务队列调入执行过程中,新建的微任务可以"插队"宏任务!
补充解释:
任务队列中实际保存的是回调函数代码体,
对于计时器等宏任务,浏览器会开启线程立即执行计时,而其回调函数会被放入队列中;
而Promise.then等微任务只有"回调函数放入队列"后半部分,这就是两种异步任务的本质区别所在.
也就是说,宏任务一半异步执行,一半在JS线程同步执行;微任务全部在JS线程同步执行,但优先级低于同步任务.
4.宏任务和微任务的回调函数体代码都将最终会在JS线程中.
5.new Promise()构造函数代码是同步会被立即执行,其then方法才是异步的.
运行并理解以下典型示例代码:
console.log("0.开始")
window.setTimeout("f1(4)", 0)
window.setTimeout("f1(7)", 0)
new Promise(function(r){
r("3.异步微任务")
console.log("1.Promise对象")
}).then(function(q){
console.log(q)
})
function f1(c) {
console.log(c,"异步宏任务")
setTimeout(()=>{
console.log("10.结束战斗!")
}, 10)
var pro = new Promise(function(req, reject){
req(c+2)
console.log(c+1, "同步任务-创建Promise对象")
})
pro.then(function(e){
console.log(e, "异步微任务")
})
}
console.log("2.同步代码执行完毕")
参考相关博客:一篇文章理解JS中同步任务和异步任务以及宏任务与微任务的原理和执行机制
我的叙述不够严谨专业,可能存在疏漏,请多多包涵.