通过该笔记,在有异步代码同时出现时能够判断出js的执行顺序
js是单线程语言
js的Event loop是js的执行机制
如果js是多线程的话,对于一个dom元素,如果一个线程删除掉这个元素,另一个线程要修改这个元素,这是就会出现矛盾
js是单线程的,单线程在执行程序时,所走的程序路径按照连续顺序拍下来,前面的处理好才会执行后面的代码,即自上而下执行,若js没有异步的话,当前面的代码执行需要花费很多时间而与后面的代码没有关联,后面的代码就会被堵塞,影响用户体验
js异步的实现是通过事件循环来实现的
js中,代码会被划分成宏任务 (macro-task) 和微任务 (micro-task),其中,宏任务包括: 整体代码script, setTimeout, setInterval; 微任务包括: Promise, process.nextTick
代码示例:
setTimeout(function(){ console.log('定时器开始啦') }); new Promise(function(resolve){ console.log('马上执行for循环啦'); for(var i = 0; i < 10000; i++){ i == 88 && resolve(); } }).then(function(){ console.log('执行then函数啦') }); console.log('代码执行结束');
首先,js先执行script所有代码,在遇到同步代码时会先执行,异步代码则会区分宏任务和微任务。看到setTimeout时就会把它放在宏任务,再往下执行,由于promise里面的代码是同步的即先回输出 ’马上执行for循环啦’,再执行for循环,当i等于88时,会遇到resolve这个微任务,则会把它放在微任务的事件队列中,再执行for循环,接着又执行同步代码,输出‘代码执行结束’, 此次宏任务执行完毕,再执行此次留下来的微任务队列,输出‘执行then函数啦’, 当微任务队列执行完后会再执行下一个宏任务队列,输出‘定时器开始啦’
setTimeout(function(){ console.log('执行了') },3000)
上面的代码,我们一般说3秒后会执行回调函数里面的代码,但这种说法并不严谨,要记住js是单线程,如果3秒后js还在执行其他的代码,就不会执行定时器里的回调函数,得等到主线程空闲的时候才会执行,也有可能10秒后执行
console.log('head'); // 宏任务 setTimeout(() => { console.log("setTimeout1"); new Promise((resolve) => { console.log('promise2'); resolve() }).then(() => { console.log('then2'); for(let i = 0; i < 100000000; i++) { if(i == 1000000) console.log(11); } }) }) // then是微任务 new Promise((resolve, reject) => { console.log('promise'); for(let i = 0; i < 100; i++) { if(i == 90) console.log('ii'); i == 88 && resolve() } }).then(() => { console.log('then1'); new Promise((resolve) => { console.log('promise'); resolve() }).then(() => { console.log('then3'); }) setTimeout(() => { console.log('settimeout3'); },10) }) setTimeout(() => { console.log("setTimeout2"); }) console.log('footer');