1. 程式人生 > 其它 >JavaScript 非同步處理

JavaScript 非同步處理

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