1、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
2、返回的異步代碼執行順序 (.then / .catah)promise
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
promise2koa
1
4
2
5
3
6異步
3、宏任務與微任務async
- 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,第一個宏任務下的微任務, 三、time1 time2 宏任務
注意:在下一個宏任務開始以前,必須將當前主線微任務所有執行完畢,才進入下一個宏任務,也就是所謂的事件循環---eventloop。異步編程
3、async和await函數函數
async 函數是什麼?一句話,它就是 Generator 函數的語法糖,async函數就是將 Generator 函數的星號(*)替換成async,將yield替換成await,僅此而已。
async
函數的返回值是 Promise 對象,這比 Generator 函數的返回值是 Iterator 對象方便多了。你能夠用then
方法指定下一步的操做。oop
進一步說,async
函數徹底能夠看做多個異步操做,包裝成的一個 Promise 對象,而await
命令就是內部then
命令的語法糖。spa
注意,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對象的時候,一樣也阻止後面的程序的運行,也加入微任務隊列。
要有最平凡的生活,和最遙遠的夢想,即便明每天寒地凍,路遙馬亡……