集千篇理論精華,感悟對同步和異步的理解

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)
})



栗子:
new Promise( ( resolve, reject ) => {
  console.log( "promise1" )
  resolve()
} )
.then( () => {
  console.log( 1 )
} )
.then( () => {
  console.log( 2 )
} )
.then( () => {
  console.log( 3 )
} )

new Promise( ( resolve, reject ) => {
  console.log( "promise2" )
  resolve()
} )
.then( () => {
  console.log( 4 )
} )
.then( () => {
  console.log( 5 )
} )
.then( () => {
  console.log( 6 )
} )

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 自己爲同步代碼)

當函數執行的時候,一旦遇到 await 就會先返回,等到觸發的異步操做完成,再接着執行函數體內後面的語句

 

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對象的時候,一樣也阻止後面的程序的運行,也加入微任務隊列。

 

 

 

 

 

 

 

 

要有最平凡的生活,和最遙遠的夢想,即便明每天寒地凍,路遙馬亡……

相關文章
相關標籤/搜索