一、同步任务与异步任务
1.javascript是一门单线程语言,同一个时间只能做一件事(单线程与javascript引擎有关)
2.javascript里边任务分为同步任务和异步任务
3.同步任务会在主线程上排队执行,只有前一个任务执行完毕,才能执行后一个任务。异步任务不进入主线程,进入”任务队列”里边,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
1.1异步任务
1、定时器都是异步操作(setTimeout,setInterval)
2、事件绑定都是异步操作(onclick)
3、AJAX中一般我们都采取异步操作(也可以同步)
4、回调函数可以理解为异步(不是严谨的异步操作)(callback)
剩下的都是同步处理
1.2js如何实现异步操作(event Loop)
event Loop(事件循环),解决javascript单线程的问题。
例如:一个请求需要很久才会返回,单线程会阻碍程序的执行,这时就需要事件循环来解决阻碍问题。
event Loop:主线程上的同步任务执行完成之后,会推一个可执行的异步任务到主线程上执行,执行完成之后。再推一个异步任务到主线程上去执行,这样一个循环执行异步任务。
二、异步任务分类(宏任务和微任务)
2.1宏任务
定时器
事件绑定
ajax
回调函数
Node中fs可以进行异步的I/O操作
2.2微任务
Promise(async/await) => Promise并不是完全的同步,在promise中是同步任务,执行resolve或者reject回调的时候,此时是异步操作,会先将then/catch等放到微任务队列。当主栈完成后,才会再去调用resolve/reject方法执行
process.nextTick (node中实现的api,把当前任务放到主栈最后执行,当主栈执行完,先执行nextTick,再到等待队列中找)
2.3宏任务与微任务的执行
当主线程上的同步任务执行完成之后,先清理所有的微任务,再执行一个宏任务,清理所有的微任务。再执行一个宏任务,再清理所有的微任务(循环)。
三、题目
3.1
setTimeout(function(){
console.log('1');
});
new Promise(function(resolve){
console.log('2');
resolve();
}).then(function(){
console.log('3');
});
console.log('4');
解读:setTimeout是一个宏任务。
new Promise()是一个构造函数同步任务,执行console.log(2)
Promise().then()是一个微任务。
执行console.log(4)。
同步任务执行完成,执行所有的微任务console.log(2)
所有的微任务执行完成,执行一个同步任务console.log(1)。
输出:2,4,3,1
3.2
setTimeout(()=>{
new Promise(resolve =>{
resolve();
}).then(()=>{
console.log('test');
});
console.log(4);
});
new Promise(resolve => {
resolve();
console.log(1)
}).then( () => {
console.log(3);
Promise.resolve().then(() => {
console.log('before timeout');
}).then(() => {
Promise.resolve().then(() => {
console.log('also before timeout')
})
})
})
console.log(2);
解读:
1.遇到setTimeout,异步宏任务,将() => {console.log(4)}放入宏任务队列中;
2.遇到new Promise,new Promise在实例化的过程中所执行的代码都是同步进行的,所以输出1;
3.而Promise.then中注册的回调才是异步执行的,将其放入微任务队列中
遇到同步任务console.log(2),输出2;
3.主线程中同步任务执行完从微任务队列中取出任务到主线程中,输出3,此微任务中又有微任务,Promise.resolve().then(微任务a).then(微任务b),将其依次放入微任务队列中;
从微任务队列中取出任务a到主线程中,输出 before timeout;
从微任务队列中取出任务b到主线程中,任务b又注册了一个微任务c,放入微任务队列中;
从微任务队列中取出任务c到主线程中,输出 also before timeout;微任务队列为空
4.从宏任务队列中取出任务到主线程,此任务中注册了一个微任务d,将其放入微任务队列中,接下来遇到输出4,宏任务队列为空
5.从微任务队列中取出任务d到主线程 ,输出test,微任务队列为空,结束~
3.3
console.log('1')
setTimeout(()=>{
console.log('2');
new Promise(resolve=>{
console.log('3')
resolve();
}).then(()=>{
console.log('4')
})
},0)
new Promise(resolve=>{
console.log('5')
resolve();
}).then(()=>{
console.log('6')
})
setTimeout(()=>{
console.log('7');
},0)
setTimeout(()=>{
console.log('8');
new Promise(resolve=>{
console.log('9')
resolve();
}).then(()=>{
console.log('10')
})
},0)
new Promise(resolve=>{
console.log('11')
resolve();
}).then(()=>{
console.log('12')
})
console.log('13');
//1,5,11,13,6,12,2,3,4,7,8,9,10