async是什么呢?大家都说他是异步请求的终极解决方案,这也证实了,async确实蛮吊的,下面我们看一下async的具体用法
async的基本用法
async函数有很明显的特征,就是函数前有async这个关键字,跟async陪套的是await,await在async函数里,async和await都返回一个promise的函数。
{
function timeout(value,ms){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(value);
},ms);
});
}
async function asyncPrint(value,ms){
const str=await timeout(value,ms);
console.log(str);//hello world
return str;
};
asyncPrint("hello world",2000).then(res=>{
console.log(res);//hello world
});
}
- 上面是个简单的async函数例子,在两秒之后,async函数里打印出来hello world,说明async里只要遇到await,就会先执行await后面的函数,一直执行完,才执行下面的语句。
- await后面虽然跟着是promise函数,但是可以不用写then,可以直接得到返回值。
- 因为async函数返回的是promise,所以可以在async函数后面加then处理return出来的数据,这样更加清晰,代码更容易阅读,逻辑也清楚,这就是async的好处之一。
顶级 await
最外层的script
标签属性必须得有type="module"
,不然会报错,在script
标签最外层的代码块下,不用写async
(也没地方写),就可以使用await
,使用场景是可以同步加载资源初始化等
<script type="module">
function getImg(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(1111)
},2000)
})
}
const data = await getImg()
console.log(data) // 两秒之后输出:1111
</script>
async的错误处理
- 第一种情况 单个await可以直接用try catch,不用then
function getImage(url){
return new Promise((resolve,reject)=>{
let img=new Image();
img.src=url;
img.onload=()=>{
resolve("ok");
};
img.onerror=()=>{
reject("err");
};
//错误的
// setTimeout(()=>{
// show();
// },0);
//正确的
show();
console.log("执行");
});
}
async function printImg(){
try{
const img=await getImage("http://pic4.nipic.com/20091217/3885730_124701000519_2.jpg");
return img;
}catch(e){
console.log(e);// show is not defined
}
console.log("async执行");//async执行
}
printImg();
注意地方
这里需要注意一点的就是发生错误的地方必须在promise的上下文中,不然try catch捕捉不到这个错误,代码还是会报错,无法继续执行下面的代码
- 第二种就是用promise的all方法,因为all方法也是要么全部成功,要么一个失败就全失败,所以这种方法跟第一种比缺点是一样的
function getImage(url){
return new Promise((resolve,reject)=>{
let img=new Image();
img.src=url;
img.onload=()=>{
resolve("ok");
};
img.onerror=()=>{
reject("err");
};
show();
console.log("执行");
});
}
async function sPrintImg2(){
Promise.all([getImage("http://pic4.nipic.com/20091217/3885730_124701000519_2.jpg"),getImage("http://pic4.nipic.com/20091217/3885730_124701000519_2.jpg")]).then(res=>
console.log(res);
).catch(e=>
console.log(e);//show is not defined
);
}
sPrintImg2();
- 第三种就是麻烦了,对每个await用try catch抱起来,但是这种可以避免第一种或者第二种的缺点
function getImage(url){
return new Promise((resolve,reject)=>{
let img=new Image();
img.src=url;
img.onload=()=>{
resolve("ok");
};
img.onerror=()=>{
reject("err");
};
show();
console.log("执行");
});
}
async function sPrintImg3(){
try{
await getImage("http://pic4.nipic.com/20091217/3885730_124701000519_2.jpg");
}catch(e){
console.log(e);
}
try{
await getImage("http://pic4.nipic.com/20091217/3885730_124701000519_2.jpg");
}catch(e){
console.log(e);
}
console.log("第三种方法async执行");
}
sPrintImg3();
还有一个值得注意的是,await必须在async函数的上下文中的。
{
let timeout=()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("我是验证await必须放在上下文中");
},100);
});
}
//错误的
async function printTimeout(){
setTimeout(()=>{
const str=await timeout();
return str;
},0);//await is only valid in async function
}
//正确的
// async function printTimeout(){
// const str=await timeout();
// return str;
// }
printTimeout().then(res=>console.log(res));
}
如果await没有在async上下文中,就会报错,所以一定要注意这个地方
await和for of异步执行,同步输出结果
假如说有一个需求,需要按照顺序去请求并返回结果
function getResult(time){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(time)
resolve(time)
},time);
})
}
async function action(){
for await(let val of [getResult(3000),getResult(1000),getResult(2000)]){
console.log(val);//三秒后一下依顺序全部输出出来3000、1000、2000
}
}
action();
上面这样写,如果循环是promise
实例,那么就会异步执行数组里的每个promise
实例,但是for of
里的代码是不执行的,得等到全部的promise
的状态改变完了,才去执行,也就是异步执行,同步输出结果,可以满足需求
如果await
是在for of
代码块里,那么执行的就是同步了,不会异步执行
async function action(){
for (let val of [3000,1000,2000]){
let res=await getResult(val)
console.log(res);//等待三秒后3000,再等待一秒后1000,再等待二秒后2000
}
}
因为for of
是迭代器,不是forEach\filter\map
等循环函数,并且for of
的await
没有放到小括号的前面,而是放到了函数体里,所以会同步循环执行,等待第一个执行完,再循环执行第二个
如果是forEach
里面放await
呢,猜一下执行结果和顺序
[3000,1000,2000].forEach(async (val)=>{
let res=await getResult(val)
console.log(res)//等待一秒后1000,再等待一秒后2000,再等待一秒后3000
})
forEach
里面是循环的一个匿名函数,所以会循环异步执行匿名函数,里面的await
只会等待结果执行完,才会执行下面的代码
关于async await
的就介绍这么多,希望对你有所帮助,如果想看更详细的资料,请狠狠的点击我