Promise
关于Promise这里就不进行介绍,关于它的介绍可以看一下笔者之前发的这篇文章:传送门
Promise的实现可以查看这篇文章:传送门
async做了什么?
async function async1() {
console.log('async1 start');
return '我是async函数,来看看我返回了什么吧!'
}
console.log('start');
let async_1 = async1();
console.log(async_1);
从上面例子中我们可以很清晰的看到async做了什么:
async意为“异步”,作为一个关键字放在函数之前,表明此函数是一个异步函数,但是总体上代码任然是同步执行的;
async函数返回的是Promise对象,如果在async函数中使用了return关键字返回了值,这个值就会被Promise.resolve()包装成Promise对象(如果没有return,则会返回undefined),保证异步函数返回的始终是Promise对象;
await做了什么?
同样我们来通过一个例子来看一下await又做了什么
console.log('start');
function fn1() {
console.log('fn1 start');
return '我是fn1';
}
async function async1() {
console.log('async1 start');
let fn_1 = await fn1();
console.log(fn_1);
console.log('async1 end');
}
let async_1 = async1();
console.log('end');
之前我们说async函数总体上是同步执行的,但这个例子它却不是按序执行的,这是因为这里有await关键字,那await关键字做了什么,让代码没有按序执行呢?
await意为‘等待’,一般都认为await用于等待一个异步方法执行完成,但在语法上,await等待的是一个表达式,这个表达式的结果可以是Promise对象或其它值,所以,await后面可以接普通函数调用、直接量或者Promise对象,await只能在异步函数 async function中使用,否则会报错,把await放在async函数内部,await只在内部发生阻塞。
那await表达式的运算结果是怎么样的呢?
-
如果它等到的不是一个 Promise 对象(如我们上面的例子),那 await 表达式的运算结果就是它等到的内容,
-
如果他等到的是一个Promise对象,它会阻塞后面代码的执行,等着Promise对象resloved得到reslove的值,作为await表达式的运算结果
async/await和Promise比有什么优势呢?
同样的来个例子直观感受一下async/await相对于Promise的部分优势吧!
//这里使用setTimeout 来模拟我们再开发中遇到的异步任务
function adge(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num + 500)
}, 500)
})
}
//多个业务之间值存在依赖
//async/await 版本
async function business() {
let num = 0;
num = await adge(num);
num = await adge(num);
num = await adge(num);
num = await adge(num);
num = await adge(num);
console.log('我是async/await 版本的business',num);
}
//多个业务之间值存在依赖
//Promise.then 版本
function business1() {
let num = 0;
new Promise((resolve, reject) => {
resolve(num);
}).then(data => {
num = adge(data);
return num;
}).then(data => {
num = adge(data);
return num;
}).then(data => {
num = adge(data);
return num;
}).then(data => {
num = adge(data);
return num;
}).then(data => {
num = adge(data);
return num;
}).then(data => {
console.log('我是Promise 版本的business',data);
})
}
通过这个例子我们可以显而易见的看到async/await简洁这一优势,但它还有其他优势:
- 简洁:用async/await就可以像写同步代码一样,节约了不少代码,不需要多层then方法,不需要写匿名函数处理Promise的resolve值,也不需要定义多余的data变量
- 错误处理:async/await让try/catch可以同时处理同步和异步错误。但在promise中,try/catch不能处理JSON.parse的错误,try/catche会被吞掉,我们需要使用.catch,这样错误处理代码非常冗余。
- 中间值:Promise传递中间值很麻烦,⽽async/await⼏乎是同步的写法,⾮常优雅
- 错误栈:Promise链中返回的错误栈没有给出错误发生位置的线索,而async/await中的错误栈会指向错误所在的函数
- 调试:Promise再调试时不能在返回表达式的箭头函数中设置断点,如果在.then代码块中设置断点,使用Step Over快捷键,调试器不会跳到下一个.then,因为它会跳过异步代码,调试器只能跟踪同步代码。