简介
近来发现同事大佬写的代码中有await,觉得很好奇,所以抽空看了几篇文章,记录一下所学。
- await的意思就是等待。它后面可以跟一个表达式。如果是值(如字符串、数字、普通对象等等)的话,返回值就是本身的值。
- 不过最常用的是后面跟一个promise对象。await会等待这个promise的状态由pending转为fulfilled或者rejected。在此期间它会阻塞,延迟执行await语句后面的语句。
- 如果promise对象的结果是resolve,它会将resolve的值,作为await表达式的运算结果。
- 其实await与async本身就是promise化编程的一种语法糖。
具体实现
对比一下await与async本身就是promise两种写法。
// 异步promise化的函数--模拟请求后端接口
function asyncFn () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if (true) {
console.log('resolve console');
resolve('resolve return');
} else {
reject('reject return');
}
}, 2000);
})
}
// promise
asyncFn().then((res) => {
console.log(res);
}, (err) => {
console.log(err);
})
// await
try {
var res = await asyncFn();
console.log(res);
} catch(err) {
console.log(err);
}
// 如果有第二次请求的话,promise需要在then方法继续调用,再用then接受,过多的嵌套依然会增加阅读难度。而await async只需要像写同步代码一样继续书写就可以,它是解决异步编程回调地狱的终极手段。
举例
1.案例一
// ps:由于js本身现在已经限制了await必须用在async函数中,否则会报错。所以请将下面的复制粘贴到浏览器控制台查看结果
function asyncFn () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if (true) {
console.log('resolve console');
resolve('resolve return');
} else {
reject('reject return');
}
}, 2000);
});
}
var value1 = await asyncFn();
var value2 = await 'plain text';
console.log(value1);
console.log(value2);
//浏览器会依次打印 ‘resolve console’ ‘resolve return’ ‘plain text’
2.案例二
如果你对结果有疑问,可以将var value1 = await asyncFn();中的await去掉,再在浏览器控制台执行一次。
这两次对比一下,会发现第二次的resolve console是最后打印出来的,而第一次的是第一个打印的。
根本原因就是第一次代码中await阻塞了后面语句的执行,等待promise确定结果后继续执行后面语句。
3.案例三
根据前两例可想而知,如果两个await的后面跟着的都是promise对象。那么第二个await等待的时间是它本身等待的时间加上第一个await等待的时间
function asyncFn1 () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if (true) {
console.log('resolve console1');
resolve('resolve return1');
} else {
reject('reject return1');
}
}, 2000);
});
}
function asyncFn2 () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if (true) {
console.log('resolve console2');
resolve('resolve return2');
} else {
reject('reject return2');
}
}, 2000);
});
}
var value1 = await asyncFn1();
var value2 = await asyncFn2();
// 复制并执行,会发现2s后打印了‘resolve console1’,4s后打印了‘resolve console2’
思考
知道了await会阻塞代码的执行,那么如何解决阻塞代码这个弊端呢?
方法:解决这个弊端的手段就是async声明。
async function asyncFn () {
return 'async'
}
console.log(asyncFn())
控制台打印一下,会发现打印的是一个promise对象。而且是Promise.resolve对象。resolve的值就是asyncFn的函数返回值async。
注意: 如果函数没有返回值的话,它自然返回的会是Promise.resolve(undefined)。
其实之所以async声明能解决await的阻塞问题,就是因为async声明将函数作了一层promise包装,这样内部的异步操作其实就是由pending转为resolve或者reject的过程。这样函数本身就能够随意调用,函数内部的await也不会再影响到函数外部的代码执行。
最后
觉得有用的朋友请用你的金手指点一下赞,或者评论留言一起探讨技术!
参考文献:https://www.cnblogs.com/jsgoshu/p/11444404.html.