与Promise血脉相连的async/await
使用规则
凡是在前面添加了async的函数在执行后都会自动返回一个Promise对象
async function test() { } let result = test() console.log(result) //即便代码里test函数什么都没返回,我们依然打出了Promise对象
await必须在async函数里使用,不能单独使用
async test() { let result = await Promise.resolve(‘success‘) console.log(result) } test()
await后面需要跟Promise对象,不然就没有意义,而且await后面的Promise对象不必写then,因为await的作用之一就是获取后面Promise对象成功状态传递出来的参数。
function fn() { return new Promise((resolve, reject) => { setTimeout(() => { resolve(‘success‘) }) }) } async test() { let result = await fn() //因为fn会返回一个Promise对象 console.log(result) //这里会打出Promise成功后传递过来的‘success‘ } test()
同步与异步
在async
函数中使用await
,那么await
这里的代码就会变成同步的了,意思就是说只有等await
后面的Promise
执行完成得到结果才会继续下去,await
就是等待,这样虽然避免了异步,但是它也会阻塞代码,所以使用的时候要考虑周全。
function fn(name) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(`${name}成功`) }, 1000) }) } async function test() { let p1 = await fn(‘小红‘) let p2 = await fn(‘小明‘) let p3 = await fn(‘小华‘) return [p1, p2, p3] } test().then(result => { console.log(result) }).catch(result => { console.log(result) })
这样写虽然是可以的,但是这里await
会阻塞代码,每个await
都必须等后面的fn()
执行完成才会执行下一行代码,所以test函数执行需要3秒。如果不是遇到特定的场景,最好还是不要这样用。
测试
console.log(1) let promiseDemo = new Promise((resolve, reject) => { console.log(2) setTimeout(() => { let random = Math.random() if (random >= 0.2) { resolve(‘success‘) console.log(3) } else { reject(‘failed‘) console.log(3) } }, 1000) }) async function test() { console.log(4) let result = await promiseDemo return result } test().then(result => { console.log(5) }).catch((result) => { console.log(5) }) console.log(6) // 1 2 4 6 3 5
一个适合使用async/await的业务场景
在前端编程中,我们偶尔会遇到这样一个场景:我们需要发送多个请求,而后面请求的发送总是需要依赖上一个请求返回的数据。对于这个问题,我们既可以用的Promise的链式调用来解决,也可以用async/await来解决,然而后者会更简洁些。
使用Promise链式调用来处理:
function request(time) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(time) }, time) }) } request(500).then(result => { return request(result + 1000) }).then(result => { return request(result + 1000) }).then(result => { console.log(result) }).catch(error => { console.log(error) })
使用async/await的来处理:
function request(time) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(time) }, time) }) } async function getResult() { let p1 = await request(500) let p2 = await request(p1 + 1000) let p3 = await request(p2 + 1000) return p3 } getResult().then(result => { console.log(result) }).catch(error => { console.log(error) })
相对于使用then不停地进行链式调用, 使用async/await
会显的更加易读一些。
在循环中使用await
如果在是循环中使用await
,就需要牢记一条:必须在async函数中使用。
在for...of
中使用await
:
let request = (time) => { return new Promise((resolve) => { setTimeout(() => { resolve(time) }, time) }) } let times = [1000, 500, 2000] async function test() { let result = [] for (let item of times) { let temp = await request(item) result.push(temp) } return result } test().then(result => { console.log(result) }).catch(error => { console.log(error) })