背景
接口的异步请求方式经历了一系列的变化,由最古老的方式(自己封装 XMLHttpRequest
/ ActiveXObject
);到 jQuery 一招先的年代 ajax
大行其道;再到后面 Promise
的出现后,所有的请求的方式都改成了使用 window.fetch
/ 类 fetch
的请求方式直接返回一个 Promise 作为请求结果返回,解决了前两方式最容易出现的回调地狱的问题。但使用 Promise.then
的方式还是有一定的局限性,虽然可以使用 Promise.all
来支持迸发请求,但使用起来还不是很爽。直到 ES 7 的 async
/ await
的出现,
让你完全告别回调地狱的烦恼,写异步像写同步一样爽。
使用 async
/ await
的异步调用的写法
这里以 Vue 中使用 axios
请求为例
// 前置:axios 接口请求时已做好拦截处理,直接调用 axios 请求时,要么直接返回 data 封装后的正确结果,要么直接抛出异常 getUserName () { // 获得用户名接口 return axios({ method: 'post', url: '/api/getUserName', data: { xxx, yyy } }) } getMobile () { // 获得到手机号接口 return axios({ method: 'post', url: '/api/getMobile', data: { xxx, yyy } }) } getDetail (userName, mobile) { // 获得 detail 信息的接口依赖于前面 getUserName 的接口及 getMobile 接口。 return axios({ method: 'post', url: '/api/getDetail', data: { userName, mobile } }) } async getDetailByUserNameNMobile () { // 结果拼接,【注意:async 里面的所有异步或者同步代码都变成同步一行行执行】 try { const userName = await this.getUserName() const getMobile = await this.getMobile() const result = await this.getDetail(userName, getMobile) console.log('结果是:', result) } catch (e) { // 异常处理 console.log(e) } }
使用 async
/ await
polyfill 新版的 es 6 异步请求方式 window.fetch
// 参考 https://github.com/bailicangdu/vue2-elm/blob/master/src/config/fetch.js const baseUrl = 'http://localhost:3000'; // 可换成自己的 export default async (url = '', data = {}, type = 'GET', method = 'fetch') => { type = type.toUpperCase(); url = baseUrl + url; if (type == 'GET') { let dataStr = ''; // 数据拼接字符串 Object.keys(data).forEach(key => { dataStr += key + '=' + data[key] + '&'; }) if (dataStr !== '') { dataStr = dataStr.substr(0, dataStr.lastIndexOf('&')); url = url + '?' + dataStr; } } if (window.fetch && method == 'fetch') { let requestConfig = { credentials: 'include', method: type, headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, mode: "cors", cache: "force-cache" } if (type == 'POST' || type == 'PUT' || type == 'PATCH' || type == 'DELETE') { requestConfig = { ...requestConfig, body: JSON.stringify(data) } } try { const response = type == 'GET' ? await fetch(url) : await fetch(url, requestConfig); const responseJson = await response.json(); return responseJson; } catch (error) { throw new Error(error); } } else { return new Promise((resolve, reject) => { let requestObj; if (window.XMLHttpRequest) { requestObj = new XMLHttpRequest(); } else { requestObj = new ActiveXObject; } let sendData = ''; if (type == 'POST' || type == 'PUT' || type == 'PATCH' || type == 'DELETE') { sendData = JSON.stringify(data); } requestObj.open(type, url, true); requestObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); requestObj.send(sendData); requestObj.onreadystatechange = () => { if (requestObj.readyState == 4) { if (requestObj.status == 200) { let obj = requestObj.response if (typeof obj !== 'object') { obj = JSON.parse(obj); } resolve(obj) } else { reject(requestObj) } } } }) } }