一、promise本身是同步还是异步呢?
众所周知,Promise是ES6提出的解决异步编程导致陷入回调地狱问题的,那么Promise是同步的还是异步的?可以确定的是,Promise本身是同步的,而他的.then和.catch为异步的。
举个栗子:
console.log(1)
let a = new Promise((res,rej) => {
console.log(2);
});
console.log(3);
let b = new Promise((res,rej) => {
console.log(4);
});
console.log(5); //1,2,3,4,5
二、返回的异步代码执行顺序 (.then / .catah)
console.log(1)
let a = new Promise((res,rej) => {
console.log(2);
res();
});
console.log(3);
let b = new Promise((res,rej) => {
console.log(4);
res();
});
console.log(5);
a.then(() => { //先执行a,是因为.then是一个微任务,而且a最先进入微任务队列,所以现在执行a,在执行b,但都必须是在等到同步代码结束之后在进入执行队列;
console.log(6)
})
b.then(() => {
console.log(7)
})栗子:
promise1
promise2
1
4
2
5
3
6
三、宏任务与微任务
- JS是一种单线程语言,代码执行顺序(同步代码先执行---->等同步代码执行完毕异步代码在执行)主线任务清空之后,异步进入任务队列,开始从任务队列进入到主线程。 - 异步任务里面又存在宏任务和微任务。(同步代码不存在宏任务与微任务一说) - 宏任务:定时器 / **script**。 - 微任务:.then
<script>
console.log('start'); //同步
setTimeout(()=>{ //宏任务
console.log('time1');
})
new Promise((resolve)=>{
console.log('promise'); //同步
resolve();
})
.then(()=>{ //.then是异步 微任务
console.log('then');
})
setTimeout(()=>{ // 宏任务
console.log('time2');
})
console.log('外部console'); //同步
</script>
执行顺序:
1、首先同步代码先依次执行;
star,promise 外部console
2、then,第一个宏任务下的微任务,
3、time1 time2 宏任务
注意:在下一个宏任务开始之前,必须将当前主线微任务全部执行完毕,才进入下一个宏任务,也就是所谓的事件循环---eventloop。

三、async和await函数
async 函数是什么?一句话,它就是 Generator 函数的语法糖,async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。
async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。
进一步说,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。
注意,await之后的代码必须等await语句执行完成后(包括微任务完成),才能执行后面的,也就是说,只有运行完await语句,才把await语句后面的全部代码加入到微任务行列,所以,在遇到await promise时,必须等await promise函数执行完毕才能对await语句后面的全部代码加入到微任务中,所以, 在等待await Promise.then微任务时, 1.运行其他同步代码, 2.等到同步代码运行完,开始运行await promise.then微任务, 3.await promise.then微任务完成后,把await语句后面的全部代码加入到微任务行列, 4.根据微任务队列,先进后出执行微任
console.log(1)
async function async1(){
console.log('async1 start')
await async2() //在此先做返回,将后面所有的代码放到异步队列,
console.log('async1 end')
}
async function async2(){
console.log('async2')
}
async1();
console.log('i am koala')//结果:
1
async1 start
async2
i am koala
async1 end
async 函数返回一个 Promise 对象,(promise 本身为同步代码)
async function t1() {
console.log(1)
console.log(2)
await new Promise(resolve => {
setTimeout(() => {
console.log('t1p')
resolve()
}, 5000)
})
await console.log(3)
console.log(4)
}
async function t2() {
console.log(5)
console.log(6)
await Promise.resolve().then(() => console.log('t2p'))
console.log(7)
console.log(8)
}
t1()
t2()
console.log('end')
1
2
5
6
end
t2p
7
8
t1p
3
4
async function async1() {
console.log( 'async1 start' )
await async2()
console.log( 'async1 end' )
}
async function async2() {
console.log( 'async2' )
}
console.log( 'script start' ) //属于一个同步代码,优先于async返回的promise执行,在async内部!
setTimeout( function () {
console.log( 'setTimeout' )
}, 0 )
async1();
new Promise( function ( resolve ) {
console.log( 'promise1' )
resolve();
} ).then( function () {
console.log( 'promise2' )
} )
console.log( 'script end' )//执行结果
script start
async1 start
async2
promise1
script end
promise2
async1 end
setTimeout
async function t1 () {
console.log(1) //1
console.log(2) //2
new Promise( function ( resolve ) {
console.log( 'promise3' ) //3
resolve();
} ).then( function () {
console.log( 'promise4' )
} )
await new Promise( function ( resolve ) { //如果它等到的是一个 promise 对象,await 也会暂停async后面的代码,先执行async外面的同步代码,
//等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果
console.log( 'b' ) //4
resolve();
} ).then( function () {
console.log( 't1p' )
} )
console.log(3)
console.log(4)
new Promise( function ( resolve ) {
console.log( 'promise5' )
resolve();
} ).then( function () {
console.log( 'promise6' )
} )
}
setTimeout( function () {
console.log( 'setTimeout' )
}, 0 )
async function t2() {
console.log(5)
console.log(6)
await Promise.resolve().then(() => console.log('t2p')) //属于promise方法,不是对象!
console.log(7)
console.log(8)
}
t1()
new Promise( function ( resolve ) {
console.log( 'promise1' ) //同步代码
resolve();
} ).then( function () {
console.log( 'promise2' )
} )
t2()
console.log('end');//执行结果;
1
2
promise3
b
promise1
5
6
end
promise4
t1p
promise2
t2p
3
4
promise5
7
8
promise6
setTimeout
分析:

当遇见第一个await之后,阻止后面的承誉德执行,加入微任务队列;执行其他同步代码,但是5,6先于end之前执行,是因为t2在end之前调用。
总结:await后面如果等到的是promise对象,执行完resolve之后,阻止后面程序的运行,加入微任务队列,如果是promise方法,也就是不是promise对象的时候,同样也阻止后面的程序的运行,也加入微任务队列。

要有最平凡的生活,和最遥远的梦想,即使明天天寒地冻,路遥马亡……