async 和 await被称为js异步的最终解决方案
,那么我们来了解下:
async:异步方法,
async function getNum(num) {
return num++
}
getNum(1);
// 很平常的使用,但async返回的Promise()对象,不管里面有没有return,只是return的话在then()方法中能取到return的值,如果return,那么就是Promise.resolve(返回值),如果没有返回值,那么就是Promise.resolve()
await:等待执行完毕
// await只支持在async的方法中使用
// await后面可以跟任何js表达式
// await后面跟的是Promise对象,则会造成async函数的停止直到它后面跟的Promise对象的状态被resovle或者reject
// await后面跟的是正常表达式则立即执行
// 一个比较简单的例子
function normalFn() {
console.log('normal')
}
function promiseFn(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise sleep ' + time + ' ms')
}, time)
})
}
async function handleFn() {
console.log('start');
let a = await normalFn();
console.log(a);
let b = await promiseFn(2000);
console.log(b);
}
// 执行结果为:
'start'
'normal'
undefined // 因为a = normalFn(),而非a = function normal() {},方法执行后没有任何返回,所以就undefined了,如果你安排一个返回值,那么就不会undefined了,你可以在normalFn方法中试试在添加个return,那样就不会undefined了
Promise() // handleFn()方法返回的一个Promise对象
'promise sleep 2000 ms' // 因为setTimeout归属于宏任务,所以在微任务都执行完毕之后才进行执行,你也可以试试0s,它依旧是最后一个才出现
// 然后我们举例一个入门级的例子:
// 例子1:我们有个方法,需要统计3次计算的总和,但是这3次计算分别都非常耗时
function getNum(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(Math.floor(Math.random()*10))
}, time)
})
}
async function getSum() {
let num1 = await getNum(1000);
let num2 = await getNum(2000);
let num3 = await getNum(3000);
console.log(11); // 会发现11和下面的内容是同时出现的,说明await是等到执行结束或者又返回才进行下一步
console.log(num1 + ':' + num2 + ':' + num3)
}
getSum();
// 例子2:我们有个方法,里面依次循环计算3次,且每次计算都需要上一轮的结果作为后一轮的数据
function getResult(param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(param)
}, 2000)
})
}
async function getStr() {
let str1 = await getResult('str1');
let str2 = await getResult(str1 + 'str2');
let str3 = await getResult(str2 + 'str3');
console.log(str3);
}
getStr();
// 接着我们来了解async如何接受错误
// 一般都知道用reject,但是怎么接收呢?
function errHandle() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('error handle by advisedly');
}, 1000);
})
}
async function correctFn() {
let msg = await errHandle();
console.log(msg);
}
correctFn(); // 这样并不能正确的拿到报错信息
// 我们需要这么改:
async function correctFn() {
try {
let msg = await errHandle();
console.log(msg);
} catch(err) {
console.log(err); // 这里接收了reject
}
}
// 有人会想这么改:虽然也能抓到,但是个人不太喜欢,因为有种又陷入到无限Promise的感觉
correctFn().catch(e => {console.log('er'+e)})
// 常用实例:
// 多个请求,所有请求都结束之后才取消加载动画
function request(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('请求成功');
}, time)
})
}
// 这是错误的写法,会阻塞异步请求
async function initFn() {
let req1 = await request(1000);
let req2 = await request(1000);
let req3 = await request(1000);
console.log('加载动画取消ing');
}
// 这才是正确操作
async function initFn() {
let req1 = request(1000);
let req2 = request(1000);
let req3 = request(1000);
await Promise.all([req1, req2, req3]);
console.log('加载动画取消ing');
}
// 注意点:await要求在async方法中,且不能被其他方法包裹
// 这样是无法正确输出的。
// 报错提示:Uncaught SyntaxError: await is only valid in async function
async function demo() {
let arr = [1,2,3,4,5];
arr.forEach(item => {
await console.log(item)
})
}
// 正确写法:
async function demo() {
let arr = [1,2,3,4,5];
for (let i=0; i<arr.length; i++) {
await console.log(arr[i])
}
}
网友评论