关于js异步编程前世今生,从回调函数到事件监听到发布订阅到Promise,网上有很多解释,所以本文仅做对于异步编程的简单记录详情可见其它blog:
javascript异步编程的前世今生,从onclick到await/async
阮一峰es6入门async 函数
场景前言:
在封装判断是否为wifi组件时,其中用到了一个异步操作,若想拿到结果需要通过回调函数的方式,因此考虑到了是否可以不用回调的方式,产生了这篇文章,模拟场景代码如下:
var re = 2;
function time(){
setTimeout(function(){
re = 3;
},300);
console.log(re);//output 2
}
time();
在如上代码中settimeout
执行了等待300ms的异步操作,所以输出的re
值并没有被改变。如果希望最后拿到的值为执行300ms之后的值,尝试方式如下:
回调函数:
无论是ajax
还是事件处理,在异步操作中最常用的函数就是回调函数,上述代码改成回调方式如下:
var re = 2;
function time(cb){
setTimeout(function(){
re = 3;
cb(re)
},300);
}
time(function(data){
console.log(data)//output 3
});
这种回调函数是比较普遍的写法,但是当回调层数多了之后,就会变成函数中层层嵌套的cb
,看着比较乱,而且当时的代码场景中只有一个异步场景,并不想启用回调函数。所以又尝试了promise
Promise:
promise用来传递异步操作的消息,可为异步操作的结果提供统一的api,也就是说Promise优化了代码的回调方式,使代码更易维护,并没有对异步操作进行任何改变,将上述代码更改成如下方式:
var re = 2;
function test(){
function time(){
return new Promise(function(resolve, reject){
setTimeout(function(){
re = 3;
resolve(re);
},300);
})
}
time().then(function(data){
console.log(data)//output 3
})
console.log(re)//output 2
};
test();
从上述结果可以看到,我执行得到的结果仍然是2,Promise并没有改变异步的操作。如此又尝试了async/await
方式.
Async/Await
async
函数返回一个Promise
对象,可以使用then
方法添加回调函数,函数执行时,遇到await
就会先返回,等到触发的异步操作完成,再执行函数体后面的语句,await
后面的函数应该是promise
对象的实例,从下面代码看出在test
函数里面打印出来的re
值是经过异步函数更改过的,但是我们如果return re
的值,打印test函数仍然不能得到re
的值,因为async
返回的是promise
对象,所以test
函数还是要通过调用then
方法获得返回值。
var re = 2;
async function test(){
function time(){
return new Promise(function(resolve, reject){
setTimeout(function(){
re = 3;
resolve();
},300);
});
}
await time()
console.log(re);//output 3
return re;
}
test().then(status=>console.log(status)) //output 3
进行到这里发现虽然最后async可以等待异步执行结束再执行其后的函数体,但如果从获得返回值上来说,仍是要走回调函数的,我最开始希望可以通过最后输出var result = test()
这样的方式拿到异步操作后的re
其实并没有实现,不知道有没有其它的方法,还请告知。如文中有错误还请指出。
个人博客:
进击的程序茗
网友评论