0%

async/await让异步操作同步执行

前言

我们经常会遇到这样的麻烦事,多个函数按顺序执行,返回结果却不是我们预期的顺序,原因一般是由于异步操作引起的,所以呢,我们需要一种解决方案来处理这种问题,从而使得异步操作按照同步的方式来执行,这样我们就可以控制异步操作输出结果的顺序了

异步操作会带来什么问题

异步操作可能会许多的问题,下面是常见的两种

1.函数执行的结果并不是按照顺序返回

1
2
3
4
5
6
7
8
9
10
11
12
function fn1(){
console.log(111)
setTimeout(function(){
console.log('wait me 3000')
},3000)
}
function fn2(){
console.log(222)
}
fn1();
fn2();

1
2
3
4
//结果
//111
//222
//wait me 3000

上面的代码,如果你期待的结果是

1
2
3
//111
//wait me 3000
//222

那就错了,因为fn1函数里面还有一个函数setTimeout,这两个函数是异步执行的,而fn1fn2是同步执行的,先执行fn1再执行fn2,在执行fn1的时候打印结果111,三秒后再执行setTimeout,但是在这三秒之前已经执行完了fn2

2.在外部获取不到异步函数里的值

下面我们看一个最简单的例子,我的需求是要在fn1函数外面打印msg

1
2
3
4
5
6
function fn1(){
setTimeout(function(){
msg='wait me 3000';
},3000);
}
fn1();

那么怎么样才能获取到msg

使用回调函数

1
2
3
4
5
6
7
8
9
function fn1(callback){
setTimeout(function(){
msg='wait me 3000';
callback(msg);
},3000);
}
fn1(data=>{
console.log(data);//wait me 3000
});

使用Promise

1
2
3
4
5
6
7
8
9
10
11
function fn1(){
return new Promise(function(res,rej){
setTimeout(function(){
msg='wait me 3000';
res(msg);
},3000);
})
}
fn1().then(data=>{
console.log(data)
})

关于Promise的信息可以参考

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

async/await解决方案

async/await的作用就是使异步操作以同步的方式去执行

异步操作同步化?

可以使用Promise中的then()来实现,那么async/await与它之间有什么区别呢

1.async函数返回的是一个Promise对象

如果一个函数加了async关键词,这个函数又有返回值,在调用这个函数时,如果函数执行成功,内部会调用Promise.solve()方法返回一个Promise对象,如果函数执行出现异常,就会调用Promise.reject()方法返回一个promise对象

要想获取到async函数的执行结果,就要调用Promisethencatch来给它注册回调函数

1
2
3
4
async function fn(){
return '111'
}
console.log(fn());//Promise { '111' }

既然是Promise对象,因此可以使用then()获取返回的结果

1
2
3
4
5
6
async function fn(){
return '111'
}
fn().then(data=>{
console.log(data)//111
})

2.await

上面介绍了async的作用,一般情况下,asyncawait配合使用才能使异步操作同步化,await就是等待的意思,等待某一个函数执行完之后,后面的代码才能开始执行

1
2
3
4
5
6
7
8
9
10
11
12
13
function fn1(){
return new Promise(resolve=>{
setTimeout(function(){
msg='wait me 3000';
resolve(msg)
},3000);
});
}
async function asyncCall(){
var result=await fn1();
console.log(result);
}
asyncCall();

如果我们没有等待fn1执行完之后再打印result,那么有可能得到是undefined

总结

aysnc await可以让我们以同步的方式编写异步代码

在很多的时候,我们是希望按照同步的方式来获得异步函数的结果,比如登录时,我们必须要在后台返回匹配成功的信息之后才能进行页面跳转,因此,使异步操作同步化这是很重要的知识点,但是这种方案是基于Promise的基础之上的,因此在学习该知识时,一定要对Promise有充分的理解

参考链接

https://juejin.cn/post/6844903984889593863