当前位置:首页 > 科技  > 软件

不要在循环await啦,异步操作的六个最佳实践!

来源: 责编: 时间:2024-04-15 18:12:41 239观看
导读Hello,大家好,我是 Sunday。前两天有个同学在面试中被问到了一个问题:“如果在请求多个不同的接口,那么应该如何去做?” 该同学回答说:“我们可以把这些接口放到一个数组中,然后通过 for 循环来循环请求!”嗯...这确是是一个

Hello,大家好,我是 Sunday。4TQ28资讯网——每日最新资讯28at.com

前两天有个同学在面试中被问到了一个问题:“如果在请求多个不同的接口,那么应该如何去做?” 该同学回答说:“我们可以把这些接口放到一个数组中,然后通过 for 循环来循环请求!”4TQ28资讯网——每日最新资讯28at.com

嗯...这确是是一个方式,不过这并不好。再加上异步问题现在已经成了面试中的常见问题,所以,今天咱们就来说一下 异步请求的最佳实践,帮助大家解决异步编程,以及面试问题。4TQ28资讯网——每日最新资讯28at.com

01:不使用 await 的循环请求

我们不应该在循环内使用 await。 而是可以利用 promise.all 方法:4TQ28资讯网——每日最新资讯28at.com

// ❌async function fn(reqs) {  const results = [];  for (const req of reqs) {    // 每次循环迭代都会延迟到整个异步操作完成    results.push(await req);  }  return results;}// ✅async function fn(reqs) {  // 存储所有异步操作的 Promise  const promises = reqs.map((req) => req);  // 所有异步操作都已经开始,现在等待它们全部完成  const results = await Promise.all(promises);  return results}

02:不要在 promise 中执行返回操作

不要在 Promise 构造函数中返回值。 从那里返回的值是无用的。 它们也不影响 Promise 的状态。4TQ28资讯网——每日最新资讯28at.com

  • 正确的方法是使用 resolve 传递值。
  • 如果有错误,则使用 reject 传递错误。
// ❌new Promise((resolve, reject) => {    // 返回没有意义    if (b) {        return result;    }});// ✅new Promise((resolve, reject) => {    // 利用 resolve 传递    if (b) {        resolve(result);        return;    }});

03:避免竞态问题

看以下代码,你认为最终打印会是多少?4TQ28资讯网——每日最新资讯28at.com

// ❌let totalPosts = 0;async function getPosts(userId) {  // 模拟获取用户的帖子数量  const users = [{ id: 1, posts: 5 }, { id: 2, posts: 3 }];  // 模拟异步延迟  await sleep(Math.random() * 1000);  // 返回对应用户的帖子数量  return users.find((user) => user.id === userId).posts;}async function sleep (time) {  return new Promise((resolve, reject) => {    setTimeout(() => {      resolve()    }, time)  })}async function addPosts(userId) {  // 将用户的帖子数量加到总帖子数上  totalPosts += await getPosts(userId);}// 并行地获取两个用户的帖子数量,并在全部获取完毕后输出总帖子数await Promise.all([addPosts(1), addPosts(2)]);console.log('帖子数量:', totalPosts);

执行以上代码,你可能会打印 3 或 5,而不是 8。4TQ28资讯网——每日最新资讯28at.com

这个原因就是因为 竞态条件 问题而导致的。当在单独的函数调用中更新值时,更新不会反映在当前函数作用域中。 因此,这两个函数都将其结果添加到初始的 TotalPosts 值 0 中。4TQ28资讯网——每日最新资讯28at.com

以下是避免竞态条件的方式:4TQ28资讯网——每日最新资讯28at.com

// ✅let totalPosts = 0;async function getPosts(userId) {  const users = [{ id: 1, posts: 5 }, { id: 2, posts: 3 }];  await sleep(Math.random() * 1000);  return users.find((user) => user.id === userId).posts;}async function sleep (time) {  return new Promise((resolve, reject) => {    setTimeout(() => {      resolve()    }, time)  })}async function addPosts(userId) {  const posts = await getPosts(userId);  totalPosts += posts; // 变量被读取并立即更新}await Promise.all([addPosts(1), addPosts(2)]);console.log('帖子数量:', totalPosts);

04:避免回调地狱

这个问题大家应该很好理解,直接看代码即可4TQ28资讯网——每日最新资讯28at.com

// ❌async1((err, result1) => {  async2(result1, (err, result2) => {    async3(result2, (err, result3) => {      async4(result3, (err, result4) => {        console.log(result4);      });    });  });});// ✅const result1 = await asyncPromise1();const result2 = await asyncPromise2(result1);const result3 = await asyncPromise3(result2);const result4 = await asyncPromise4(result3);console.log(result4);

05:避免直接返回 await

尽量避免直接返回 await ,特别是在需要 try..catch 的时候:4TQ28资讯网——每日最新资讯28at.com

// ❌async () => {  try {    return await getUser(userId);  } catch (error) {    // 输出错误  }}// ✅async () => {  try {    const user = await getUser(userId);    return user;  } catch (error) {    // 输出错误  }}

06:reject 最好配合 Error 使用

// ❌Promise.reject('这是一个错误');// ✅Promise.reject(new Error('这是一个错误'));


4TQ28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-83620-0.html不要在循环await啦,异步操作的六个最佳实践!

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 要么返回错误值,要么输出日志,别两样都做

下一篇: 聊聊如何使用 Python 实现 RSA 加密

标签:
  • 热门焦点
  • 6月iOS设备好评榜:第一蝉联榜首近一年

    作为安兔兔各种榜单里变化最小的那个,2023年6月的iOS好评榜和上个月相比没有任何排名上的变化,仅仅是部分设备好评率的下降,长年累月的用户评价和逐渐退出市场的老款机器让这
  • 5月安卓手机好评榜:魅族20 Pro夺冠

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年5月1日至5月31日,仅限国内市场。第一名:魅族20 Pro好评率:97.50%不得不感慨魅族老品牌还
  • JavaScript 混淆及反混淆代码工具

    介绍在我们开始学习反混淆之前,我们首先要了解一下代码混淆。如果不了解代码是如何混淆的,我们可能无法成功对代码进行反混淆,尤其是使用自定义混淆器对其进行混淆时。什么是混
  • 一篇聊聊Go错误封装机制

    %w 是用于错误包装(Error Wrapping)的格式化动词。它是用于 fmt.Errorf 和 fmt.Sprintf 函数中的一个特殊格式化动词,用于将一个错误(或其他可打印的值)包装在一个新的错误中。使
  • 从零到英雄:高并发与性能优化的神奇之旅

    作者 | 波哥审校 | 重楼作为公司的架构师或者程序员,你是否曾经为公司的系统在面对高并发和性能瓶颈时感到手足无措或者焦头烂额呢?笔者在出道那会为此是吃尽了苦头的,不过也得
  • 中国家电海外掘金正当时|出海专题

    作者|吴南南编辑|胡展嘉运营|陈佳慧出品|零态LT(ID:LingTai_LT)2023年,出海市场战况空前,中国创业者在海外纷纷摩拳擦掌,以期能够把中国的商业模式、创业理念、战略打法输出海外,他们依
  • 大厂卷向扁平化

    来源:新熵作者丨南枝 编辑丨月见大厂职级不香了。俗话说,兵无常势,水无常形,互联网企业调整职级体系并不稀奇。7月13日,淘宝天猫集团启动了近年来最大的人力制度改革,目前已形成一
  • 机构称Q2国内智能手机销量同比下滑4% vivo份额重回第1

    7月29日消息,根据市场调查机构Counterpoint Research公布的最新报告,2023年第2季度中国智能手机销量同比下降4%,创新自2014年以来第2季度销量新低。报
  • Windows 11发布,微软一改往常对老机型开放的态度

    距离 Windows 11 发布已经过去一周,在过去一周里,很多数码爱好者围绕其对 Android 应用的支持、对老机型的升级问题展开了激烈讨论。与以往不同的是,在这次大
Top