async
async是用来生成异步函数的,它的后面可以是函数声明,函数表达式,箭头函数等。async函数生成的是一个promise,后面可以接.then或者.catch进行处理。如果async函数里面return一个数字或者字符串或者promise,那么它就会返回一个成功的promise,异步函数捕获的值为那个数字或者字符串。
let p = async function add(){
return 'haha'
}
p().then(console.log)
//haha
如果抛出一个错误,那么就是返回一个失败的promise,异步函数捕获的的错误值为throw的值
let p = async function add(){
throw 3
}
p().then((res)=>{
console.log(res)
},(e)=>{
alert(e)
})
// 会弹出3
但是拒绝的promise的错误不会被异步函数捕获。
let p = async function add(){
Promise.reject(3)
}
p().then((res)=>{
console.log(res)
},(e)=>{
alert(e)
})
//报错
await
因为async函数是异步函数,他不会马上完成任务,但是它相对于需要调用next()方法来逐步执行的生成器函数(Generator)来说,他又实现了自动执行。所以它自然需要一种暂停执行或者重新执行的能力。使用await可以使异步函数暂停执行,等待期约的解决。
let p = async ()=>{
console.log(1)
let p1 = await Promise.resolve(3)
console.log(p1)
console.log(4)
}
p()
console.log(2)
// 1 2 3 4
从上面的代码可以看出,await后面的代码被延后执行了,也就是等待Promise.resolve()被解决,并且有了返回值之后才会执行后面的。
项目中,下面的代码是比较常见的用法
let axios = function(type,url){
return new Promise((resolve,reject)=>{
let xhr = new XMLHttpRequest();
xhr.open(type,url)
xhr.send()
xhr.onreadystatechange=function(){
if(xhr.readyState===4){
if(xhr.status>=200&&xhr.status<300){
// 这种情况代表发送成功
resolve(Response)
}
}
}
})
};
let p= async()=>{
console.log('在接受数据前的操作')
let res=await axios('GET','promise.php')
console.log(res)
console.log('在接受数据之后的操作')
}
p()
await抛出错误的获取方式
1、await后面如果是promise.reject()或者是抛出的错误,那么async会立刻返回一个失败的promise,捕获到的值是抛出的错误。那么await后面的操作就不会在执行了
let p =async function pp(){
await (()=>{
throw 3
})()
console.log(4)
}
p().catch(console.log)
// 3
let p =async function pp(){
await Promise.reject(3)
console.log(4)
}
p().catch(console.log)
// 3
2、try/catch:可以直接利用try/catch来进行捕获错误,那么他后面的操作还是会被执行的
let p =async function pp(){
try {
await Promise.reject(3)
} catch (error) {
console.log(error)
}
console.log(4)
}
p()
// 3 4
异步函数策略
1、实现sleep
在不堵塞程序的情况下,让异步函数暂停执行一段时间,其本质还是使用setTimeout(),等待一段时间之后,再让await后面的promise的状态发生改变,await才能得到resolve的值。然后后面的程序才能够执行。
function sleep(delay){
return new Promise((resolve)=>{
setTimeout(resolve,delay)
})
}
async function wait(){
await sleep(3000)
console.log(4)
}
wait()
// 等待3秒后输出:4
2、平行执行
function time(id){
let t = Math.random*1000
return new Promise((resolve)=>{
setTimeout(()=>{
console.log(`${id},finished`)
resolve()
},t)
})
}
let p=async ()=>{
let t0 = Date.now()
await time(1)
await time(2)
await time(3)
console.log(Date.now()-t0)
}
p()
// 1,finished;2,finished;3,finished;6
虽然所有的Promise之间并没有什么依赖关系,但是还是以此执行的。
3、串行执行promise
async function two(x){
return x+2
};
async function three(x){
return x+3
};
async function five(x){
return x+5
}
async function ten(x){
for (const fn of [two,three,five]){
x=await fn(x)
}
return x
}
ten(5).then(console.log)
使用async/await执行串行期约更加的方便!