async 和 await

11/17/2020 JavaScriptAsyncES6

# 文章目录

# 一、介绍

async 函数是使用 async 关键字声明的函数。 async 函数是 AsyncFunction 构造函数的实例, 并且其中允许使用 await 关键字。async 和 await 关键字让我们可以用一种更简洁的方式写出基于 Promise 的异步行为,而无需刻意地链式调用 promise

# 二、async 函数

  1. async 修饰的函数返回值无论如何为都为 promise 对象 ,
  2. promise 对象的结果由 async 函数执行的返回值决定

怎么决定的呢?有如下三点:

  • return 7 大数据类型的值 返回的是成功的 promise 对象,空 return 也是

  • 抛出错误,返回的结果是一个失败的 Promise

    • 返回的结果如果是一个 Promise 对象:

      1. 里边 Promise 的状态 影响(关联)外边 async 的状态.且 resolve 与 reject 方法的参数就是 async Promise 的值
      2. 如果抛出 rejected,则 async 的状态为失败,且 PromiseValue 就是抛出错误的值
// async函数  返回的结果不是一个 Promise 类型的对象,返回的结果就是成功 Promise 对象(抛出异常除外)
async function fn() {
  // return 7大数据类型的值 返回的是成功的promise对象,空return也是
  // return 'str'; // return;

  // 抛出错误,返回的结果是一个失败的 Promise
  // throw new Error('出错啦!')

  // 返回的结果如果是一个 Promise 对象:
  // 1. 里边 Promise 的状态 影响外边 async 的状态.且 resolve与reject方法的参数就是 async Promise的值
  // 2. 如果抛出错误,则 async的状态为失败,且 PromiseValue就是抛出错误的值
  return new Promise((resolve, reject) => {
    resolve("成功"); // fulfilled
    // reject('失败') // rejected
  });
}

const result = fn();
console.log(result);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 三、await 关键字

  1.       await 必须写在 async 函数中
    
  2.       awalt 右侧的表达式一般为 promise对象
    
  3.       await 返回的是 promise成功的值
    
  4.       await 的 promise失败了,就会抛出异常,需要通过try… catch捕获处理
    
// 创建 Promise 对象
const p = new Promise((resolve, reject) => {
  resolve("成功");
  // reject('失败')
});

// await 要放在 async 函数中
async function main() {
  try {
    // await 修饰的 Promise对象,返回状态为成功(fulfilled)时的值,状态为 rejected时,会抛出异常
    let result = await p;
    console.log(result);
  } catch (e) {
    // 在 catch 语句中可以捕获异常,得到 Promise 失败(rejected)的结果
    console.log(e);
  }
}

// 调用函数
main();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 四、案例

# 4.1 async 搭配 await 读取多个文件(Node.js)

首先需要有 node 环境的支持,然后创建三个文件:

c.txt:

c
1

java.txt

java
1

javascript.txt

javascript
1

它们都在 fiel 文件夹下。

然后看我们的 主文件:

// 引入 fs 模块
const fs = require("fs");

// 读取
function readC() {
  return new Promise((resovle, reject) => {
    fs.readFile("./file/c.txt", (err, data) => {
      // 如失败
      if (err) reject(err);
      // 成功
      resovle(data);
    });
  });
}

function readJava() {
  return new Promise((resovle, reject) => {
    fs.readFile("./file/java.txt", (err, data) => {
      // 如失败
      if (err) reject(err);
      // 成功
      resovle(data);
    });
  });
}

function readJavaScript() {
  return new Promise((resovle, reject) => {
    fs.readFile("./file/javascript.txt", (err, data) => {
      // 如失败
      if (err) reject(err);
      // 成功
      resovle(data);
    });
  });
}

// 声明一个 async 函数
async function main() {
  // 获取c内容
  let resultC = await readC();

  // 获取java内容
  let resultJava = await readJava();

  // 获取 javascript内容
  let resultJs = await readJavaScript();

  console.log(resultC.toString());
  console.log(resultJava.toString());
  console.log(resultJs.toString());
}

main();
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

接下来运行该文件,输出:

c;
java;
javascript;
1
2
3

可以看到我们的代码,非常的优雅,完美的解决了以前的回调地狱问题。

# 4.2 async 搭配 await 发送 Ajax 请求

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Ajax</title>
</head>

<body>
  <script>
    // 发送Ajax请求,返回的结果是一个 Promise 对象
    function sendAjax(url) {
      return new Promise((resolve, reject) => {
        // 1.创建对象
        const Ajax = new XMLHttpRequest()

        // 2.初始化
        Ajax.open('GET', url)

        // 3.发送
        Ajax.send()

        // 4.事件绑定
        Ajax.onreadystatechange = function () {
          if (Ajax.readyState === 4) {
            if (Ajax.status >= 200 && Ajax.status < 300) {
              // 成功
              resolve(Ajax.response)
            } else {
              // 失败
              reject(Ajax.status)
            }
          }
        }
      })
    }

    // 测试

    // 一、Promise方法实现
    // const result = sendAjax('https://api.apiopen.top/getJoke').then(value => {
    //   console.log(value);
    // }, err => {
    //   console.log(err);
    // })

    // 二、async await 实现
    async function main(){
      // 发送 Ajax请求
      let result = await sendAjax('https://api.apiopen.top/getJoke')
      console.log(result);
    }
    main()
  </script>
</body>

</html>
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

可以看到我们的代码非常的优雅,几乎和我们写同步的代码没有什么区别。

最后更新于: 2021年9月15日星期三晚上10点10分
Faster Than Light
Andreas Waldetoft / Mia Stegmar