非同步-promise、async、await
阿新 • • 發佈:2020-01-11
下面程式碼列印結果是?
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變數,還避免了巢狀程式碼。