asyncawait基本理解及项⽬案例(结合Promi)
ES2017 标准引⼊了 async 函数,使得异步操作变得更加⽅便。
1.async/await场景
这是⼀个⽤同步的思维来解决异步问题的⽅案,当前端接⼝调⽤需要等到接⼝返回值以后渲染页⾯时。
2.名词解释
async
async的⽤法,它作为⼀个关键字放到函数前⾯,⽤于表⽰函数是⼀个异步函数,因为async就是异步的意思, 异步函数也就意味着该函数的执⾏不会阻塞后⾯代码的执⾏,async 函数返回的是⼀个promi 对象,可以使⽤then⽅法添加回调函数。当函数执⾏的时候,⼀旦遇到await就会先返回,等到异步操作完成,再接着执⾏函数体内后⾯的语句。
await
await的含义为等待。意思就是代码需要等待await后⾯的函数运⾏完并且有了返回结果之后,才继续执⾏下⾯的代码。这正是同步的效果。
3.基本讲解
简单案例:
async function timeout() {
return 'hello world'
}
console.log(timeout());
console.log('虽然在后⾯,但是我先执⾏');hears
原来async 函数返回的是⼀个promi 对象,如果要获取到promi 返回值,我们应该⽤then ⽅法, 继续修改代码
async function timeout() {
return 'hello world'
}
timeout().then(result => {
console.log(result);
})
console.log('虽然在后⾯,但是我先执⾏');
我们获取到了"hello world', 同时timeout 的执⾏也没有阻塞后⾯代码的执⾏,和 我们刚才说的⼀致。
你可能注意到控制台中的Promi 有⼀个resolved,这是async 函数内部的实现原理。如果async 函数中有返回⼀个值 ,当调⽤该函数时,内部会调⽤solve() ⽅法把它转化成⼀个promi 对象作为返回,但如果timeout 函数内部抛出错误呢? 那么就会调⽤ject() 返回⼀个promi 对象, 这时修改⼀下timeout 函数
async function timeout(flag) {
if (flag) {
return 'hello world'
} el {
throw 'my god, failure'
}
}
console.log(timeout(true)) // 调⽤solve() 返回promi 对象。
console.log(timeout(fal)); // 调⽤ject() 返回promi 对象。
如果函数内部抛出错误, promi 对象有⼀个catch ⽅法进⾏捕获。
timeout(fal).catch(err => {
console.log(err)
})
await是等待的意思,那么它等待什么呢,它后⾯跟着什么呢?其实它后⾯可以放任何表达式,不过我们更多的是放⼀个返回promi 对象的表达式。注意await 关键字只能放到async 函数⾥⾯
现在写⼀个函数,让它返回promi 对象,该函数的作⽤是2s 之后让数值乘以2
// 2s 之后返回双倍的值
function doubleAfter2conds(num) {
return new Promi((resolve, reject) => {
tTimeout(() => {
resolve(2 * num)
}, 2000);
} )
}
现在再写⼀个async 函数,从⽽可以使⽤await 关键字, await 后⾯放置的就是返回promi对象的⼀个表达式,所以它后⾯可以写
上 doubleAfter2conds 函数的调⽤
async function testResult() {
let result = await doubleAfter2conds(30);
console.log(result);
}
现在调⽤testResult 函数
testResult();
打开控制台,2s 之后,输出了60.
拾音
现在我们看看代码的执⾏过程,调⽤testResult 函数,它⾥⾯遇到了await, await 表⽰等⼀下,代码就暂停到这⾥,不再向下执⾏了,它等什么呢?等后⾯的promi对象执⾏完毕,然后拿到promi resolve 的值并进⾏返回,返回值拿到之后,它继续向下执⾏。具体到 我们的代码, 遇到await 之后,代码就暂停执⾏了, 等待doubleAfter2conds(30) 执⾏完毕,doubleAfter2conds(30) 返回的
promi 开始执⾏,2秒 之后,promi resolve 了, 并返回了值为60, 这时await 才拿到返回值60, 然后赋值给result, 暂停结束,代码才开始继续执⾏,执⾏ console.log语句。
就这⼀个函数,我们可能看不出async/await 的作⽤,如果我们要计算3个数的值,然后把得到的值进⾏输出呢?
async function testResult() {
let first = await doubleAfter2conds(30);
let cond = await doubleAfter2conds(50);
let third = await doubleAfter2conds(30);
console.log(first + cond + third);
海蒂和爷爷观后感}
6秒后,控制台输出220, 我们可以看到,写异步代码就像写同步代码⼀样了,再也没有回调地域了。
Vue项⽬案例
普通案例:
methods: {
getLocation(phoneNum) {
return axios.post('/mm接⼝', {
phoneNum
})
},
getFaceList(province, city) {
return axios.post('/nn接⼝', {
province,
city
})
},
getFaceResult () {
工商银行存款利率if (res.status === 200 && res.data.success) {
let province = res.data.obj.province;
let city = res.data.obj.city;
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 = Location(this.phoneNum);
if (location.data.success) {
let province = location.data.obj.province;
let city = location.data.obj.city;
let result = FaceList(province, city);
if (result.data.success) {
this.faceList = result.data.obj;
}
}
公考真题库
}
现在代码的书写⽅式,就像写同步代码⼀样,没有回调的感觉,⾮常舒服。
现在就还差⼀点需要说明,那就是怎么处理异常,如果请求发⽣异常,怎么处理? 它⽤的是try/catch 来捕获异常,把await 放到 try 中进⾏执⾏,如有异常,就使⽤catch 进⾏处理。
async getFaceResult () {
try {
let location = Location(this.phoneNum);
if (location.data.success) {
let province = location.data.obj.province;
let city = location.data.obj.city;
let result = FaceList(province, city);
if (result.data.success) {
this.faceList = result.data.obj;
}
校长新年致辞
}
} catch(err) {
console.log(err);
}
}
Vue项⽬案例(封装)
http.js
'u strict'
import axios from 'axios'
import qs from 'qs'
quest.u(config => {
// loading
return config
}, error => {
ject(error)
})
学习情境
spon.u(respon => {
return respon
}, error => {
spon)
})
function checkStatus (respon) {
// loading
// 如果http状态码正常,则直接返回数据
if (respon && (respon.status === 200 || respon.status === 304 || respon.status === 400)) {
return respon
// 如果不需要除了data之外的数据,可以直接 return respon.data
}
// 异常状态下,把错误信息返回去
return {
status: -404,
msg: '⽹络异常'
}
}
function checkCode (res) {
// 如果code异常(这⾥已经包括⽹络错误,服务器错误,后端抛出的错误),可以弹出⼀个错误提⽰,告诉⽤户 if (res.status === -404) {
alert(res.msg)
}
if (res.data && (!res.data.success)) {
alert(_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; chart=UTF-8' }
}).then(
(respon) => {
return checkStatus(respon)
}
)
},
get (url, params) {
return axios({
method: 'get',
baURL: 'cnodejs/api/v1',
url,
params, // get 请求时带的参数
timeout: 10000,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
}).then(
(respon) => {
return checkStatus(respon)
}
)
.then(
(res) => {
return checkCode(res)
}
)
}
}
api.js
export default {
getCode: '127.0.0.1:8888/.....'
}
auth.vue