async 和 await(详解)
一、async 和 await
promise
使用.then
链式调用,但也是基于回调函数async/await
更加优雅的异步编程的写法
1.它是消灭异步回调的终极武器
2.它是同步语法,也就是用同步的写法写异步的代码
案例1:promise异步加载图片
- 分别使用 .then 和 await 来获取结果
- 区别
1.await 完全没有回调函数
2.await 是同步写法,异步操作
3.await 后面不仅仅可以接 promise对象,还可以接 async 函数
//里面函数为AJAX,因此是异步任务
let loadImg = (url)=>{const p = new Promise((resolve,reject)=>{let newImg = document.createElement("img")newImg.src = urlnewImg.onload = function(){resolve(newImg)}newImg.error = function(){reject(new Error('Could not load Image at url'))}})return p
}//通过 .then 来获取结果
loadImg(url1).then((img)=>{console.log(img.width,img.height)document.body.appendChild(img)return loadImg(url2)}).then((img)=>{console.log(img.width,img.height)document.body.appendChild(img)}).catch((err)=>{console.log(err)})//使用 async 和 await 的方法来写,立即执行函数
(async function(){// loadImg(url1) 返回 promise 对象// await 可以拿到从 resolve 传递过来的 dom 对象const img1 = await loadImg(url1) document.body.appendChild(img1)const img2 = await loadImg(url2) document.body.appendChild(img2)
})()//await 接 async 函数
async function loadImg1(){const img1 = await loadImg(url1)return img1
}
(async function(){//img1可以拿到 resolve 里面的值const img1 = await img1 document.body.appendChild(img1)
})()
二、async/await 和 promise的关系
- async/await 是消灭异步回调的终极武器
- 但和Promise并不排斥,两者相辅相成
- 执行 async 函数,返回的是 Promsie 对象
- await 相当于 Promise 的 then ,then指的是成功,不指失败
- try…catch 可捕获异常,代替了 Promise的 catch
1.async
async function fn(){return 100
}
console.log(fn()) //返回一个成功态的promise对象,result 是 100
fn().then(data=>{console.log(data)}
) // 100
2.await
- await 后面接 Promise
1.await p1相当于是p1.then
,并且只是成功态的then
2.await 和 then 的区别就是:then还需要传回调进去,但 await 可以直接得到值
(async function(){const p1 = Promise.resolve(300) //一个成功态的promise对象,且传了result为300const res = await p1 // return 值console.log(res) // 300
})
- await 和 .then 的区别
fn().then(data=>{console.log(data)}
)//await直接通过返回值来接收daita, return data
const res = await fn()
- await 接数值
1.await后面跟的不是promise对象而是数值时,会自动包装成成功态的promise对象
2.并且传值给 resolve 为400
(async function(){const res = await 400 //Promise.resolve(400)console.log(res) //400
})()
- await 接 async 函数
(async function(){const res = await fn() //fn()会返回promise对象,原理一样console.log(res) //400
})()
- await 接promise 为空
1.什么都打印不出来
2.因为 new Promise 里面没有任何状态改变,而await一直在等待状态改变
3.只有状态改变了,await才会允许执行后面的代码
(async function(){const p = new Promise(()=>{})const res = await pconsole.log(res)console.log("success")
})()
- await 接 promise 为 error
1.会出现报错
2.await相当于成功态的 .then ,都没有成功,因此不会执行后面的代码
3.因为JS是单线程的
4.解决:使用 try…catch 偷偷解决掉 error,保证代码运行
——捕获到错误就不会影响后面的输出
(async function(){const p = Promise.reject("error")const res = await pconsole.log(res)console.log("success")
})() //什么都打印不出来
(async function(){const p = Promise.reject("error")try{const res = await pconsole.log(res)}catch(error){console.log(error)}console.log("success")
})() //打印出 error 和 success
三、执行顺序
- 代码中存在 await,则需要等待该行执行完才执行下面的代码
function timeout(){return new Promise(resolve=>{setTimeout(()=>{console.log(1)resolve()//成功态})})
}//情况一
async function fn(){timeout()console.log(2)
}
fn() //打印出 2 一秒后 1//情况2
async function fn(){await timeout()console.log(2)
}
fn() //1秒后打印出 1 2
//写法二
function timeout(){return new Promise(resolve=>{setTimeout(()=>{resolve(1)//成功态,传递参数1})})
}
async function fn(){const res = await timeout() //需要一个变量来接收await return的参数console.log(res)console.log(2)
}
fn() //1秒后打印出 1 2
四、async 和 await 的实质
- Promise一般用来解决层层嵌套的回调函数
- async/await 是消灭异步回调的终极武器
- JS还是单线程,还是得有异步,还是得基于 event loop(轮询机制)
- async/await 只是一个语法糖
案例2 :请求多份数据,但后一份数据的请求必须依赖上一份数据的请求结果
- 解决:
1.可以使用promise的.then 链式层层调用
2.也可以使用 async/await ,用同步的代码来解决异步问题
——依次获取数据,完全是同步的写法
——await会等待该行代码完全运行,才执行后面的代码
async function getDate(){const res1 = await request("./a.json")console.log(res1)const res1 = await request("./b.json")console.log(res2)const res1 = await request("./c.json")console.log(res3)
}