1. 程式人生 > >非同步-promise、async、await

非同步-promise、async、await

下面程式碼列印結果是?
setTimeout(()=>{
  console.log(1)
})
new Promise((resolve,reject)=>{
  console.log(2)
  resolve()
})
.then(()=>{
  console.log(3)
})
new Promise((resolve,reject)=>{
  console.log(4)
  resolve()
})
.then(()=>{
  console.log(5)
})
setTimeout(()=>{
  console.log(6)
})
console.log(7)

/*
    2
    4
    7
    3
    5
    1
    6
    
*/

解析這道題之前我們先了解幾個知識點~~~~

資料載入方案

  • 同步載入
  • 非同步載入 : 事件 , 定時器 , ajax

js單執行緒語言

為什麼是單執行緒語言?

dom操作

  • 如果js是多執行緒語言,第一個執行緒執行把dom物件刪除,另一個執行緒執行把dom物件新增
同步程式碼非同步程式碼載入順序 : event loop (事件迴圈)
  • 先執行同步程式碼,非同步任務掛起
        setTimeout(function(){
            console.log(1);
        },0)
        console.log(2);
        //執行結果 : 2 , 1 -->先執行console,log(2) setTimeout非同步掛起 

巨集任務和微任務

  • 巨集任務一般是:包括整體程式碼script,setTimeout,setInterval。

  • 微任務:Promise,process.nextTick。

巨集任務的非同步 和微任務的非同步同時都有 優先執行 微任務

瞭解了這些知識,我們回到第一題
   1、首先:promise 的建立是同步的,then、catch是非同步,所以先執行同步打印出2 4 7
   2、非同步的 1、3、5、6,進入事件佇列。
   3、setTimeout 為巨集任務,promise為微任務,先執行微任務,所以3、5先被打印出來,1、6後被打印出來

promise 承諾 是一個物件

非同步程式碼同步執行

1.三個狀態 : pending (進行時) resolve (成功狀態), reject(失敗的狀態).

2.使用時 需要例項化 new Promise()

3.Promise() 引數是一個回撥函式

4.在回撥函式中有兩個引數

​ resolve reject

5.promise返回值為promise

6.promise的方法

  • .then()
兩個引數 都是回撥函式
如果promise 執行resolve方法   執行為.then裡面第一個回撥
如果promise 執行reject方法   執行為.then裡面第二個回撥
  • .catch()
當promise執行了reject方法的時候  執行的是.catch裡面的回撥
  • .all()
  • .race()

非同步

js是單執行緒,防止被堵塞 node中將所有i/o變成非同步

非同步的過多巢狀會造成回撥地獄

promise的鏈式呼叫可以解決回撥地獄

async
  • 可以修飾一個函式,被修飾的函式返回promise物件
  • async 返回值可有也可以沒有,返回的是返回的資料就是then 接收的資料,不返回資料相當於undefined
async function text(){
    return true
}
text()
.then((data)=>{
    console.log("ok")
})
.catch((err)=>{
    console.log("err")
})
await
  • 在async函式內部使用,將promise變成同步
  • await關鍵字後面跟Promise物件
//求和操作
function num1(){
  return new Promise((resolve,reject)=>{
    setTimeout(()=>{
      resolve(1)
    },1000)
  })
}

function num2(){
  return new Promise((resolve,reject)=>{
    setTimeout(()=>{
      resolve(2)
    },500)
  })
}

async function sum(){
    let res1=await num1()
    let res2=await num2()
    reyturn res1 + res2
}
sum()
.then((data)=>{  
    console.log(data)
})
  • 使用async函式可以讓程式碼簡潔很多,不需要像Promise一樣需要些then,不需要寫匿名函式處理Promise的resolve值,也不需要定義多餘的data變數,還避免了巢狀程式碼。