目录

🛩 Promise 的 async 和 await

🔗 相关链接 :

简而言之, async / await 的使用是 更加舒适使用 Promise 的方式。

# async 函数

  • 返回值为 Promise 对象
  • Promise 对象的结果async 函数执行的返回值决定。

(注:与 .then 相似)

使用 async 「修饰」的函数表示:这个函数总是返回一个 Promise ,其他值将自动被包装在一个 resolved 的 promise 中。

🌰 例子:

async function main(){
    // 返回值为非promise
    // return 123 // 成功的promise
    // 返回的是promise对象
    /*return new Promise((resolve, reject)=>{
        resolve('ok') // 结果由这个结果决定
    })*/
    throw "error" 
}

let result = main()
console.log(result)
1
2
3
4
5
6
7
8
9
10
11
12

# await 表达式

async function func() {
  let value = await promise;
}
1
2
3
  • await 右侧的表达式一般为 Promise 对象,但也可以是其它的值。
  • 如果表达式为 Promise 对象,await 返回的是 Promise 成功的值
  • 如果表达式是其他值直接将此值作为 await 的返回值

关键字 await 让 JavaScript 引擎等待直到 promise 完成并返回结果。

注意:

  • await 必须写在 async 函数中,但 async 函数中可以没有 await 。( await 写在普通函数中会报错)
  • 如果 await 的 Promise 失败了,就会抛出异常,需要通过 try … catch … 捕获处理。

提示

await 实际上会暂停函数的执行,直到 promise 状态变为 settled,然后以 promise 的结果继续执行。这个行为不会耗费任何 CPU 资源,因为 JavaScript 引擎可以同时处理其他任务:执行其他脚本,处理事件等。

相比于 promise.then ,它只是获取 promise 的结果的一个更优雅的语法。并且也更易于读写。

🌰 例子:

async function main(){
  let p = new Promise((resolve, reject)=>{
    // resolve('ok')
    reject('error')
  })

  // let result = await p; // 右侧为promise的情况
  // console.log(result);
  // let result2 = await 123; // 右侧为其他类型
  // console.log(result2);

  try {
    let result3 = await p; // 右侧为promise失败
  } catch (e) {
    console.warn(e) // 获取到失败的结果
  }
}

main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

提示

async / await 可以与 Promis.all 结合使用:当需要同时等待多个 promise 时,可以使用 Promise 包装起来,然后使用 await

let results = await Promise.all([
  fetch(url1),
  fetch(url2),
  ...
]);
1
2
3
4
5

如果出现 error,也会正常传递,从失败了的 promise 传到 Promise.all ,然后变成能通过使用 try..catch 在调用周围捕获到的异常。

# asyncawait 结合

🌰 例子(读取文件):

const fs = require('fs')
const util = require('util')
const mineReadFile = util.promisify(fs.readFile)

// 使用async与await
async function main() {
    try {
        let data1 = await mineReadFile('./resource/1.html')
        let data2 = await mineReadFile('./resource/2.html')
        let data3 = await mineReadFile('./resource/3.html')
        console.log(data1 + data2 + data3)
    } catch (err) {
        console.warn(err)
    }

}

main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  • 相比于使用回调函数实现,减少写抛出异常 try-catch 结构。
  • asyncawait 结合后,少用回调函数。

🌰 例子(发送 AJAX 请求):

<button id="btn">获取</button>

<script>
    function sendAJAX(url) {
        return new Promise((resolve, reject)=>{
            const xhr = new XMLHttpRequest();
            xhr.open('GET', url)
            xhr.send();
            xhr.onreadystatechange = function () {
                if(xhr.readyState === 4) {
                    if(xhr.status >= 200 && xhr.status < 300) {
                        // 成功请求
                        resolve(xhr.response)
                    } else {
                        // 失败请求
                        reject(xhr.status)
                    }
                }
            }
        })
    }

    let btn = document.querySelector("#btn")
    btn.addEventListener('click', async function(){
        let text = await sendAJAX('https://api.apiopen.top/getJoke')
        console.log(text)
    })

</script>
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

# 总结

  • async 关键字对函数的作用:

    • 让这个函数总是返回一个 promise。
    • 允许在该函数内使用 await
  • Promise 前的关键字 await 使 JavaScript 引擎等待该 promise 确定状态,然后:

    1. 如果有 error,就会抛出异常 ,就像那里调用了 throw error 一样。
    2. 否则,就返回结果。
📢 上次更新: 2022/09/02, 10:18:16