詞法定義
-
async
async 是“異步”的簡寫, async 用於申明一個異步的 function
-
await
await 可以認為是 async wait 的簡寫,await 用於等待一個異步方法執行完成。
借檢https://www.cnblogs.com/airen123/p/9543490.html
特點:
- asayc的用法,它作為一個關鍵字放到函數前面,這樣普通函數就變為了異步函數
- 異步async函數調用,跟普通函數的使用方式一樣
- 異步async函數返回一個promise對象
- async函數配合await關鍵字使用(阻塞代碼往下執行)
是異步方法,但是阻塞式的
案例
模擬出一個搖色子的異步操作,先通過一個方法三秒之后拿到一個篩子數,第二步進行輸出
//基本用法的async函數 let asyncFun = async function(){ return 1 } console.log(asyncFun()) //會返回一個promise對象 //使用場景 //搖色子方法 function dice(){ return new Promise((resolve,reject)=>{ let sino = parseInt(Math.random()*6+1) //生成一個1~6之間的隨機小數 setTimeout(()=>{ resolve(sino) },2000) }) } //異步方法 async function text(){ let n= await dice() //await 關鍵字后面調用搖色子方法執行完畢之后,才進行變量賦值 console.log("搖出來"+n) //最后打印出搖出來的數 } text()
async/await的優點
-
方便級聯調用
:即調用依次發生的場景; -
同步代碼編寫方式
: Promise使用then函數進行鏈式調用,一直點點點,是一種從左向右的橫向寫法;async/await從上到下,順序執行,就像寫同步代碼一樣,更符合代碼編寫習慣; -
多個參數傳遞:
Promise的then函數只能傳遞一個參數,雖然可以通過包裝成對象來傳遞多個參數,但是會導致傳遞冗余信息,頻繁的解析又重新組合參數,比較麻煩;async/await沒有這個限制,可以當做普通的局部變量來處理,用let或者const定義的塊級變量想怎么用就怎么用,想定義幾個就定義幾個,完全沒有限制,也沒有冗余工作; -
同步代碼和異步代碼可以一起編寫
: 使用Promise的時候最好將同步代碼和異步代碼放在不同的then節點中,這樣結構更加清晰;async/await整個書寫習慣都是同步的,不需要糾結同步和異步的區別,當然,異步過程需要包裝成一個Promise對象放在await關鍵字后面; -
sync/await是對Promise的優化:
async/await是基於Promise的,是進一步的一種優化,不過在寫代碼時,Promise本身的API出現得很少,很接近同步代碼的寫法;
使用場景
async主要來處理異步的操作,
需求:執行第一步,將執行第一步的結果返回給第二步使用。在ajax中先拿到一個接口的返回數據,后使用第一部返回的數據執行第二步操作的接口調用,達到異步操作。
Vue項目案例
普通案例promise:
methods: { getLocation(phoneNum) { return axios.post('/one接口', { phoneNum }) }, getFaceList(province, city) { return axios.post('/two接口', { province, city }) }, getFaceResult () { this.getLocation(this.phoneNum).then(res => { if (res.status === 200 && res.data.success) { let province = res.data.obj.province; let city = res.data.obj.city; this.getFaceList(province, city).then(res => { if(res.status === 200 && res.data.success) { this.faceList = res.data.obj } }) } }).catch(err => { console.log(err) }) } }
這時你看到了then 的鏈式寫法,有一點回調地域的感覺。現在我們在有async/ await 來改造一下。
async/ await案例:
首先把 getFaceResult 轉化成一個async 函數,就是在其前面加async, 因為它的調用方法和普通函數的調用方法是一致,所以沒有什么問題。然后就把 getLocation 和getFaceList 放到await 后面,等待執行, getFaceResult 函數修改如下:
async getFaceResult () { let location = await this.getLocation(this.phoneNum); if (location.data.success) { let province = location.data.obj.province; let city = location.data.obj.city; let result = await this.getFaceList(province, city); if (result.data.success) { this.faceList = result.data.obj; } } }
現在代碼的書寫方式,就像寫同步代碼一樣,沒有回調的感覺,非常舒服。
現在就還差一點需要說明,那就是怎么處理異常,如果請求發生異常,怎么處理? 它用的是try/catch 來捕獲異常,把await 放到 try 中進行執行,如有異常,就使用catch 進行處理。
async getFaceResult () { try { let location = await this.getLocation(this.phoneNum); if (location.data.success) { let province = location.data.obj.province; let city = location.data.obj.city; let result = await this.getFaceList(province, city); if (result.data.success) { this.faceList = result.data.obj; } } } catch(err) { console.log(err); } }
Vue項目案例(封裝)
http.js
'use strict' import axios from 'axios' import qs from 'qs' axios.interceptors.request.use(config => { // loading return config }, error => { return Promise.reject(error) }) axios.interceptors.response.use(response => { return response }, error => { return Promise.resolve(error.response) }) function checkStatus (response) { // loading // 如果http狀態碼正常,則直接返回數據 if (response && (response.status === 200 || response.status === 304 || response.status === 400)) { return response // 如果不需要除了data之外的數據,可以直接 return response.data } // 異常狀態下,把錯誤信息返回去 return { status: -404, msg: '網絡異常' } } function checkCode (res) { // 如果code異常(這里已經包括網絡錯誤,服務器錯誤,后端拋出的錯誤),可以彈出一個錯誤提示,告訴用戶 if (res.status === -404) { alert(res.msg) } if (res.data && (!res.data.success)) { alert(res.data.error_msg) } return res } export default { post (data,url) { return axios({ method: 'post', url: url, data: qs.stringify(data), timeout: 10000, headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' } }).then( (response) => { return checkStatus(response) } ) }, get (url, params) { return axios({ method: 'get', baseURL: 'https://cnodejs.org/api/v1', url, params, // get 請求時帶的參數 timeout: 10000, headers: { 'X-Requested-With': 'XMLHttpRequest' } }).then( (response) => { return checkStatus(response) } ).then( (res) => { return checkCode(res) } ) } }
api.js
export default { getCode: 'http://127.0.0.1:8888/.....' }
auth.vue
import http from '../../utils/http' import api from '../../utils/api' methods: { fetchData: async function () { var that = this var code = Store.fetchYqm(); let params = { inviteCode: code } const response = await http.post(params,api.getCode) var resJson = response.data; } }
公司的項目案例