主题
async+await异步解决方案
前言
async await 是ES7中的语法,是基于promise之上的一个语法糖,可以让异步操作更加简单明了,首先我们需要使用async关键字将函数标记为异步函数,异步函数就是指返回值为promise对象的函数,比如浏览器的fetch就是一个异步函数,在异步函数中我们可以调用其他异步函数,不过我们不在使用then,而是使用一个更加简洁的await语法,awiat会等待promise完成之后直接返回最终的结果,需要注意的是,await看上去等待函数的执行,但是await等待过程中,js同样可以处理其他的任务,比如更新界面,运行其他程序代码等待,这是因为await底层是基于promise和事件循环机制实现的
1. async函数
mdn上对async的解释:async函数是使用async关键字声明的函数。 async函数是AsyncFunction构造函数的实例, 并且其中允许使用await关键字。async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise
简单的说: async是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象resolve的值。因此对async函数可以直接then,返回值就是then方法传入的函数。
async函数的返回值:async函数返回一个Promise,这个promise要么会通过一个由async函数返回的值被解决,要么会通过一个从async函数中抛出的(或其中没有被捕获到的)异常被拒绝。
js
// async基础语法
async function fn(){
console.log(1);
return 1;
}
fn().then(val=>{
console.log(val) // output:1 1
})
async function fn1(){
console.log('Promise');
return new Promise(function(resolve,reject){
resolve('Promise2')
})
}
fn1().then(val => {
console.log(val); //output: Promise Promise2
})
2. await关键字
await 也是一个修饰符,只能放在async定义的函数内。可以理解为等待。async函数遇到await后会等待后面的逻辑执行完(异步等待),再执行awiat下面的逻辑
await后面如果是Promise对象:可以获取Promise中返回的内容(resolve或reject的参数),且取到值后语句才会往下执行;
await后面若不是Promise对象:会把这个非promise的东西当做await表达式的结果返回。
js
async function fun(){
let a = await 1;
let b = await new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('setTimeout')
},3000)
})
let c = await function(){
return 'function'
}()
console.log(a,b,c)
}
fun(); // 3秒后输出: 1 "setTimeout" "function"
js
function log(time){
setTimeout(function(){
console.log(time);
return 1;
},time)
}
async function fun(){
let a = await log(1000);
let b = await log(3000);
let c = log(2000);
console.log(a);
console.log(1)
}
fun();
// 立即输出 undefined 1
// 1秒后输出 1000
// 2秒后输出 2000
// 3秒后输出 3000
3. async await使用中的陷进
1. 并发操作
一个async函数中写多个await,函数内的逻辑是串行执行的,也就是下一个awiat会等待上一个await完成后再执行,若要并行,可以用Promise.all解决
2. 循环中的异步操作
若我们需要再循环中执行异步操作,是不能够直接调用forEach或者map这一类方法的, 尽管我们在回调函数中写了async awiat ,但这里的forEach会立刻返回,它并不会暂停等到所有异步操作都执行完毕;若我们希望等待循环中的所有异步操作都一一执行完毕之后才继续执行,那我们还是应当使用传统的for循环,
更进一步,若我们想要循环中的所有异步操作都并发执行,一种更炫酷的方法是使用for await;这里的for循环依然会等到所有的异步操作都完成后才继续向后执行,