在JS运行机制当中,JavaScript是单线程的编程语言,简单的讲就是将JavaScript比作一个单项的管道,每次仅仅执行一个任务,执行多种任务需要进行排队执行。只有执行完前一个任务,才能执行后一个任务。
在JavaScript待执行任务中,主要分为两类
所谓同步任务,就是非耗时任务,在主线程当中直接执行的任务 例如
console.log('同步任务');
var a=1+d;
另外,当async/await的任务当中,并没有返回值,如下
async function async1(){
console.log('async1 start');
await async2();
console.log('async1 end');
}
而不是
async function async1(){
return 123;
}
上面的这种情况,此async/await所修饰方法内,可作为同步代码进行同步执行,但是其后面的代码将不作为同步代码执行。
等等都属于同步任务,同步任务,直接在JS单线程当中执行
异步任务,又称耗时任务,异步任务的执行浪费时间,容易造成线程的堵塞。 异步任务又分为微任务与宏任务。
其中,微任务主要包括Promise.then、async/await等任务
new Promise((resolve,reject)=>{
//同步执行体
}).then(value=>{
//异步任务
})
宏任务主要包括定时器、I/O等等
/*
setTimeout
setInterval
I/O
*/
在JS当中,其待执行任务的优先级为同步任务>微任务>宏任务
一个例子解释了解执行的例子,代码如下
async function async1(){
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2(){
console.log('async2');
}
console.log('script start');
setTimeout(() => {
console.log('settimeout');
}, 0);
async1();
new Promise(function(resolve){
console.log('promise1');
resolve();
}).then(function(){
console.log('Promise2')
})
console.log('script end');
首先,寻找其中的同步代码
根据js运行从上至下,首先打印的是同步代码块中的script start,之后,settimeout定时器是属于宏任务,则将其扔到宏任务队列里等待执行。接着调用async1中的方法,输出async1 start,值得主要的是两个被async和await Promise语法糖修饰的方法并未返回一个promise,所以,其方法内的代码块可以算是同步执行,所以调用async2(),并接着打印输出async2,然后被修饰的方法后的代码块不执行,也就是async1 end并不会执行,接着完成async1()的调用,然后轮到Promise执行,其Promise是属于同步代码块,而其Promise.then属于微任务,代码块,所以将promise.then中的方法扔到微任务队列当中等待执行,在之前输出promise1,然后接着执行最后一个同步代码打印输出script end,接着同步任务执行完毕,在将微任务队列拿出来执行,首先执行第一个微任务,async1()方法当中的async1 end,再接着执行第二个微任务,Promise.then当中的Promise2,由此,所有的微任务执行完毕,接着开始将宏任务队列拿出来,则执行第一个宏任务settimeout当中,打印输出settimeout,由此所有的宏任务处理完毕。然后在次将微任务、宏任务依次拿出来执行,若是没有,则持续监听,直到有任务。
此时,执行的结果顺序为
script start
async1 start
async2
promise1
script end
async1 end
Promise2
settimeout
关于代码执行过程