JavaScript 非同步處理
阿新 • • 發佈:2022-03-10
1.ES5的非同步處理
- ES5使用回撥來接收處理非同步方法的返回值,即:預定義一個回撥方法,作為引數傳入到非同步函式中,當非同步的處理結果出來後,呼叫之前的預定義回撥,並將處理結果回傳給他
//建立一個非同步返回 雙倍數值 的函式 function asyncDouble(num,cb){ // 建立標識,表示該非同步處理是否完成 var complite = false // 數值處理結果 var result = null var timeOut = Math.random() * 3 console.log('timeOut = ',timeOut) // 模擬非同步操作 setTimeout(() => { // 產生處理結果 result = num * 2 // 切換標識狀態為完成 complite = true },timeOut * 1000) // 建立定時器監聽非同步處理是否完成 var timer = setInterval(() => { // 根據標識判斷非同步處理完成,執行回撥並傳入處理結果 if(complite){ cb && cb(result) clearInterval(timer) } },100) } asyncDouble(5,function(result){ console.log(result) // 10 })
2.Promise簡介
Promise是為了解決ES5中回撥地獄而誕生的,Promise,顧名思義,就是承諾以後執行。
以下是2種方式在語法上面差別,處理成功都是執行sucesscb,失敗則執行errcb,你可以簡單的理解成,在promise中,成功回撥與失敗回撥是在非同步方法呼叫完畢後定義的,而ES5則相反,ES5中的回撥必須在非同步函式呼叫之前就定義好
//ES5處理非同步
asyncFn(params,sucesscb,errcb)
//Promise處理非同步
asyncFn(params).then(sucesscb).catch(errcb)
3.Promise的建立
Promise是一個建構函式,接收一個函式作為引數,當new一個Promise時,會把傳入的函式執行一遍(可以用一個函式把Promise包裹起來,避免定義的時候就執行程式碼)
<script> //執行到這裡時會馬上執行Promise裡面的程式碼 new Promise(function(){ console.log('hello world') //控制檯立即列印 'hello world' }) // 這個函式除非被呼叫執行,不然不會執行Promise裡面的程式碼 function promiseWrap(){ var promise = new Promise(function(resolve,reject){ console.log('hello world') }) } </script>
4.Promise的內部書寫邏輯
Promise接收兩個引數(resolve,reject),分別應對成功與失敗兩種處理結果,resolve對應的是then()的第一個引數,reject對應的就是catch()方法的引數,或者then()的第二個引數。可以這麼理解,then()的第一個引數就是對resolve的定義,而catch()的引數則是對reject的定義
<script>
// 傳入一個數字,非同步返回他的2倍值
function getDoubleAsync(num){
// 數字轉換
var num = Number(num)
var promise = new Promise(function(resolve,reject){
// 儲存處理結果的物件
var res = {}
// 模擬非同步
setTimeout(() => {
// 判斷傳入的引數是否有效
if(isNaN(num)){
res.state = 0
res.data = '錯誤的引數'
}else {
res.state = 1
res.data = num * 2
}
},1000)
// 監聽完成進度
var timer = setInterval(() => {
if(res.state === 1){
//執行成功的回撥
resolve(res)
clearInterval(timer)
}else if(res.state === 0){
//執行失敗的回撥
reject(res)
clearInterval(timer)
}
},100)
})
// 返回promise
return promise
}
// 傳入正常的引數
getDoubleAsync(10).then(function(res){
console.log("執行了成功的回撥") //執行了成功的回撥
console.log(res) //{state: 1, data: 20}
},function(res){
console.log("執行了失敗的回撥")
console.log(res)
})
// 傳入錯誤的引數
getDoubleAsync("x").then(function(res){
console.log("執行了成功的回撥")
console.log(res)
},function(res){
console.log("執行了失敗的回撥") //執行了失敗的回撥
console.log(res) //{state: 0, data: "錯誤的引數"}
})
// 使用catch捕獲失敗 推薦
getDoubleAsync("x").then(function(res){
console.log("執行了成功的回撥")
console.log(res)
}).catch(function(res){
console.log("執行了失敗的回撥") //執行了失敗的回撥
console.log(res) //{state: 2, data: "錯誤的引數"}
})
</script>
5.Async/await的使用:
- async和await關鍵字讓我們可以用一種更簡潔的方式寫出基於Promise的非同步行為,而無需刻意地鏈式呼叫promise。
- Async/await這兩個關鍵字是成對存在的,只有在用 async 宣告的function,其內部才能使用 await
- await是等待的意思,後面接收一個promise,他會一直等待promise的資料(實參)返回,然後將promise中的資料(實參)提取出來,供後面的程式碼處理,在此過程中,await後面的程式碼不會執行,處於等待狀態
例項:用Async/await處理ajax請求
async function getGameList(){ //非同步操作
try{
console.log('開始請求',new Date().getTime())
//axios是非同步方法 await會一直等待其返回結果
const result = await axios.get('/game_list.json')
//直到axios請求結果回來,才會執行後面的程式碼
console.log('資料已經回來',new Date().getTime())
}catch(err){
console.log(err)
}
}
控制檯列印:
在vue中,methods中的方法是簡寫的形式,可以這樣寫
methods:{
async getList () {
var result = await axios.post()
this.list = result.data
}
}