个人技术站点JASONWU

Keep Coding


  • 主页

  • 文章

  • 搜索

JavaScript 使用 Promise:Async/Await

新建: 2021-05-31 编辑: 2021-07-05   |   分类: JavaScript   | 字数: 2122 字

通过 ES2017 async/await 及 Promise Combinator 实现优雅的异步代码。

以同步写异步

语法糖:async/await 并没有为 JS 语言添加新特性,仅仅是为 Promise 提供了一种更易写易懂的语法。

JavaScript
 1const wait = sec =>
 2  new Promise(resolve => setTimeout(resolve, sec * 1000));
 3
 4// 通过 async/await 使用 Promise
 5(async () => {
 6  await wait(1);
 7  console.log('1秒后执行');
 8
 9  await wait(1);
10  console.log('2秒后执行');
11
12  await wait(1);
13  console.log('3秒后执行');
14
15  await wait(1);
16  console.log('4秒后执行');
17})();
18
19// Promise 原使用方式
20// wait(1)
21//   .then(() => {
22//     console.log('1秒后执行');
23//
24//     return wait(1);
25//   })
26//   .then(() => {
27//     console.log('2秒后执行');
28//
29//     return wait(1);
30//   })
31//   .then(() => {
32//     console.log('3秒后执行');
33//
34//     return wait(1);
35//   })
36//   .then(() => {
37//     console.log('4秒后执行');
38//
39//     return wait(1);
40//   });

代码求证语法糖

JavaScript
1const asyncFunc = async () => '语法糖';
2
3console.log(asyncFunc()); // Promise {<fulfilled>: "语法糖"}

错误处理

tray...catch...finally

JavaScript
 1(async () => {
 2  try {
 3    const postUrl = 'https://jsonplaceholder.typicode.com/posts/101';
 4    const postRes = await fetch(postUrl);
 5
 6    if (!postRes.ok) {
 7      throw new Error(`服务出错(${postRes.status})`);
 8    }
 9
10    const post = await postRes.json();
11
12    console.log(post);
13
14  } catch (err) {
15    console.log(err.message);
16  }
17})();

返回值

async 调用 async(推荐)

JavaScript
 1const getPost = async () => {
 2  try {
 3    const postUrl = 'https://jsonplaceholder.typicode.com/posts/1';
 4    const postRes = await fetch(postUrl);
 5
 6    return postRes.json();
 7
 8  } catch (err) {
 9    // 当作为返回值使用时,需要再抛出错误,以供外部处理
10    throw err;
11  }
12};
13
14console.log('1:开始查询');
15
16(async () => {
17  try {
18    const post = await getPost();
19    console.log(`2:获取文章${post.id}`);
20
21    console.log('3:结束查询');
22
23  } catch (err) {
24    console.log(err);
25  }
26})();
27
28// 1:开始查询
29// 2:获取文章1
30// 3:结束查询

Promise 回调

JavaScript
 1const getPost = async () => {
 2  try {
 3    const postUrl = 'https://jsonplaceholder.typicode.com/posts/1';
 4    const postRes = await fetch(postUrl);
 5
 6    return postRes.json();
 7
 8  } catch (err) {
 9    // 当作为返回值使用时,需要再抛出错误,以供外部处理
10    throw err;
11  }
12};
13
14console.log('1:开始查询');
15
16getPost()
17  .then(post => console.log(`2:获取文章${post.id}`))
18  .finally(() => console.log('3:结束查询'));
19
20// 1:开始查询
21// 2:获取文章1
22// 3:结束查询

Promise Combinator

组合多个 Promise 共同执行。

Promise.all()

JavaScript
 1const getPost = async (postId) => {
 2  const baseUrl = 'https://jsonplaceholder.typicode.com';
 3  const postUrl = `${baseUrl}/posts/${postId}`;
 4  const postRes = await fetch(postUrl);
 5  return await postRes.json();
 6};
 7
 8/*
 9(async () => {
10  // 按顺序阻塞执行 AJAX 请求,糟糕的代码!!!
11  const post1 = await getPost(1);
12  const post2 = await getPost(2);
13  const post3 = await getPost(3);
14
15  console.log([post1.id, post2.id, post3.id]);
16})();
17*/
18
19(async () => {
20  // 并行执行 AJAX 请求
21  const posts = await Promise.all([
22    getPost(1),
23    getPost(2),
24    getPost(3)
25  ]);
26
27  const postIds = posts.map(post => post.id);
28  console.log(postIds);
29})();

Short Circuit:只要有一个 Rejected Promise,就会导致 Promise.all() 结果错误。

JavaScript
1(async () => {
2  const proAll = await Promise.all([
3    Promise.resolve('成功'),
4    Promise.reject('失败')
5  ]);
6
7  console.log(proAll); // Uncaught (in promise) 失败
8})();

Promise.race()

约定俗成:以 _ 作为被忽略的变量名称,即表示在上下文中不需要的变量。

此外,_ 也是 Lodash 的默认命名空间。

JavaScript
 1const getPost = async (postId) => {
 2  const baseUrl = 'https://jsonplaceholder.typicode.com';
 3  const postUrl = `${baseUrl}/posts/${postId}`;
 4  const postRes = await fetch(postUrl);
 5  return await postRes.json();
 6};
 7
 8const timeout = sec => new Promise((_, reject) => {
 9  // 约定俗成:以 `_` 表示被忽略的变量
10  setTimeout(() => reject(new Error(`请求超时${sec}秒`)), sec * 1000);
11});
12
13(async () => {
14  const post = await Promise.race([
15    getPost(1),
16    timeout(0.18)
17  ]);
18
19  console.log(post.id);
20  // 1
21  // 或
22  // Uncaught (in promise) Error: 请求超时0.18秒
23})();

Short Circuit:只要有一个 Settled Promise,就会使 Promise.race() 返回结果。

JavaScript
 1(async () => {
 2  const proRace = await Promise.race([
 3    Promise.resolve('成功1'),
 4    Promise.reject('失败1')
 5  ]);
 6
 7  console.log(proRace); // 成功1
 8})();
 9
10(async () => {
11  const proRace = await Promise.race([
12    Promise.reject('失败2'),
13    Promise.resolve('成功2')
14  ]);
15
16  console.log(proRace); // Uncaught (in promise) 失败2
17})();

Promise.allSettled()

No Short Circuit:ES2020 引入,与 Promise.all() 类似,除了 Promise.allSettled() 一定会保证所有 Promise 都为 Settled 状态。

JavaScript
1(async () => {
2  const proAll = await Promise.allSettled([
3    Promise.resolve('成功'),
4    Promise.reject('失败')
5  ]);
6
7  console.log(proAll);
8  // [{...}, {...}]
9})();

Promise.any()

Short Circuit:ES2021 引入,与 Promise.race() 类似,除了 Promise.any() 只返回第一个 Fulfilled Promise,而忽略 Rejected Promise。

JavaScript
 1(async () => {
 2  const proAny = await Promise.any([
 3    new Promise(resolve => {
 4      console.log('执行:成功1');
 5      resolve('成功1');
 6    }),
 7    new Promise((_, reject) => {
 8      console.log('执行:失败1-1');
 9      reject('失败1-1');
10    }),
11    new Promise(resolve => {
12      console.log('执行:成功1-1');
13      resolve('成功1-1');
14    }),
15  ]);
16
17  // 执行:成功1
18  // 执行:失败1-1
19  // 执行:成功1-1
20
21  console.log(proAny); // 成功1
22})();
23
24(async () => {
25  const proAny = await Promise.any([
26    Promise.reject('失败2'),
27    Promise.resolve('成功2'),
28    Promise.resolve('成功2-1')
29  ]);
30
31  console.log(proAny); // 成功2
32})();
#Async# #Promise#

文章:JavaScript 使用 Promise:Async/Await

链接:https://www.wuxianjie.net/posts/js-async-await/

作者:吴仙杰

文章: 本博客文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议,转载请注明出处!

JavaScript OOP:原型链
HTTP 请求与响应报文格式
  • 文章目录
  • 站点概览
吴仙杰

吴仙杰

🔍 Ctrl+K / ⌘K

27 文章
9 分类
25 标签
邮箱 GitHub
  • 以同步写异步
  • 代码求证语法糖
  • 错误处理
  • 返回值
    • async 调用 async(推荐)
    • Promise 回调
  • Promise Combinator
    • Promise.all()
    • Promise.race()
    • Promise.allSettled()
    • Promise.any()
© 2021-2025 吴仙杰 保留所有权利 All Rights Reserved
浙公网安备 33010302003726号 浙ICP备2021017187号-1
0%