Iwen's blog Iwen's blog
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于

Iwen

不摸鱼的哥哥
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于
  • Vue

  • Vue进阶

  • CSS

  • ES6

  • Base

  • Core

  • Array

  • Object

  • String

  • Async

    • Ajax
    • Promise
    • Promise 回调
    • async await
      • 使用规则
      • 同步与异步
      • 优雅的错误处理方法
      • 一个适合使用async/await的业务场景
      • 在循环中使用await
      • 测试
    • 跨域
    • try catch
    • Generator async await原理
  • Browser

  • Http

  • 性能优化

  • 正则

  • 经典总结

  • 设计模式

  • 数据结构

  • 算法

  • 手写

  • TypeScript

  • 复盘
  • Async
Mr.w
2020-11-29

async await

# async/await

# 使用规则

凡是在前面添加了async的函数在执行后都会自动返回一个Promise对象

注意重点: 返回结果为Promise。

async function test() { 
    return 100; 
}
console.log(test())  // Promise {<resolved>: 100}
1
2
3
4

await必须在async函数里使用,不能单独使用

async function test() {
    let result = await Promise.resolve('success')
    console.log(result)
}
test()
1
2
3
4
5

await后面需要跟Promise对象,不然就没有意义,而且await后面的Promise对象不必写then,因为await的作用之一就是获取后面Promise对象成功状态传递出来的参数。

function fn() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('success')
        })
    })
}
async function test() {
    let result = await fn() //因为fn会返回一个Promise对象
    console.log(result)     //这里会打出Promise成功后传递过来的'success'
}
test()
1
2
3
4
5
6
7
8
9
10
11
12

# 同步与异步

在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)     // 错误的处理方法,前提是函数调用,否则往下看
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

这样写虽然是可以的,但是这里await会阻塞代码,每个await都必须等后面的fn()执行完成才会执行下一行代码,所以test函数执行需要3秒。如果不是遇到特定的场景,最好还是不要这样用。

# 优雅的错误处理方法

一般情况下async/await在错误处理方面,主要使用 try/catch,像这样

const fetchData = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('fetch data is me')
        }, 1000)
    })
}

(async () => {
    try {
        const data = await fetchData()
        console.log('data is ->', data)
    } catch(err) {
        console.log('err is ->', err)
    }
})()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 一个适合使用async/await的业务场景

在前端编程中,我们偶尔会遇到这样一个场景:我们需要发送多个请求,而后面请求的发送总是需要依赖上一个请求返回的数据。

对于这个问题,我们既可以用的Promise的链式调用来解决,也可以用async/await来解决,然而后者会更简洁些。

使用Promise链式调用来处理:

function request(time) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(time)
        }, time)
    })
}
request(500).then(result => {
    console.log(result)         // 500
    return request(result + 1000)
}).then(result => { 
    console.log(result)         // 1500
    return request(result + 1000)
}).then(result => {
    console.log(result)         // 2500
}).catch(error => {
    console.log(error)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

使用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) // 2500
}).catch(error => {
    console.log(error)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

相对于使用then不停地进行链式调用, 使用async/await会显的更加易读一些。

# 在循环中使用await

如果在是循环中使用await,就需要牢记一条:必须在async函数中使用。

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)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 测试

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)
})
console.log(8)
async function test() {
    console.log(4)
    let result = await promiseDemo
    return result
}
setTimeout(() => {
    console.log(7)
}, 0)
test().then(result => {
    console.log(5)
}).catch((result) => {
    console.log(5)
})

console.log(6)

// 1 2 8 4 6 7 3 5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Promise 回调
跨域

← Promise 回调 跨域→

最近更新
01
flex布局页面自适应滚动条问题
12-28
02
前后端分离开发请求接口跨域如何携带cookie的问题
12-28
03
怎么实现div长宽比固定width-height4比3
12-28
更多文章>
Theme by Vdoing | Copyright © 2017-2022 Iwen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式