怎样处理async/await浪费性能问题

这次给大家带来怎样处理async/await浪费性能问题,处理async/await浪费性能问题的注意事项有哪些,下面就是实战案例,一起来看一下。

前言

async/await是什么

async/await可以说是co模块和生成器函数的语法糖。用更加清晰的语义解决js异步代码。

熟悉co模块的同学应该都知道,co模块是TJ大神写的一个使用生成器函数来解决异步流程的模块,可以看做是生成器函数的执行器。而async/await则是对co模块的升级,内置生成器函数的执行器,不再依赖co模块。同时,async返回的是Promise。

从上面来看,不管是co模块还是async/await,都是将Promise作为最基础的单元,对Promise不很了解的同学可以先深入了解一下Promise。

async/await 写着很爽,不过要注意这些问题。

async/await 让我们摆脱了回调地狱,但是这又引入了 async/await 地狱的问题。

怎样处理async/await浪费性能问题

什么是 async/await 地狱

在 Javascript 中进行异步编程的时候,人们总是使用很多 await 语句,很多时候我们的语句并不需要依赖于之前的语句,这样就会导致性能问题。

async/await 地狱的例子

我们试着写一个购买披萨和饮料的程序:

(async () => { const pizzaData = await getPizzaData() // async call const drinkData = await getDrinkData() // async call const chosenPizza = choosePizza() // sync call const chosenDrink = chooseDrink() // sync call await addPizzaToCart(chosenPizza) // async call await addDrinkToCart(chosenDrink) // async call orderItems() // async call})()

登录后复制

这段代码运行没有问题。但是不是一个好的实现,因为这增加了不必要的等待。

说明

我们已经将我们的代码封装在异步 IIFE 中,按照下面的顺序执行:

得到披萨名单
获取饮料列表
从列表中选择一个披萨
从列表中选择一种饮料
将选中的披萨加入购物车
将选择的饮品加入购物车
订购购物车中的物品

问题

这里有个问题为什么从列表中选择披萨这个动作要等待获取饮料列表?这两个是没什么关联的操作。其中的关联操作有两组:

获取披萨列表 -》 选择披萨 -》 选择披萨加入购物车

获取饮料列表 -》 选择饮料 -》 选择饮料加入购物车

这两组操作应该是并发执行的。

再来看一个更差的例子

这个 Javascript 代码片段将购物车中的商品并发出订购请求。

async function orderItems() { const items = await getCartItems() // async call const noOfItems = items.length for(var i = 0; i < noOfItems; i++) { await sendRequest(items[i]) // async call }}

登录后复制

这种情况 for 循环必须等待 sendRequest() 函数完成才能继续下一次迭代。但是,我们并不需要等待。我们希望尽快发送所有请求。然后我们可以等待所有请求完成。

现在你应该已经对 async/await 地狱有跟多的了解,现在我们再来考虑一个问题

如果我们忘记 await 关键字会怎么样?

如果在调用异步函数忘记使用 await,这意味着执行该功能不需要等待。异步函数将直接返回一个 promise,你可以稍后使用。

(async () => { const value = doSomeAsyncTask() console.log(value) // an unresolved promise})()

登录后复制

或者是程序不清楚你想要等待函数执行完,直接退出不会完成这个异步任务。所以我们需要使用 await 这个关键字。

promise 有一个有趣的属性,你可以在某行代码中获取 promise,然后在其他地方中等待它 resolve,这是解决 async/await 地狱的关键。

(async () => { const promise = doSomeAsyncTask() const value = await promise console.log(value) // the actual value})()

登录后复制

如你所见 doSomeAsyncTask 直接返回一个 Promise 同时这个异步函数 doSomeAsyncTask 已经开始执行,为了得到 doSomeAsyncTask 的返回值,我们需要 await 来告诉

应该如何避免 async/await 地狱

首先我们需要知道哪些命名是有前后依赖关系的。

然后将有依赖关系的系列操作进行分组合并成一个异步操作。

同时执行这些异步函数。

我们来重写这写例子:

async function selectPizza() { const pizzaData = await getPizzaData() // async call const chosenPizza = choosePizza() // sync call await addPizzaToCart(chosenPizza) // async call}async function selectDrink() { const drinkData = await getDrinkData() // async call const chosenDrink = chooseDrink() // sync call await addDrinkToCart(chosenDrink) // async call}(async () => { const pizzaPromise = selectPizza() const drinkPromise = selectDrink() await pizzaPromise await drinkPromise orderItems() // async call})()// Although I prefer it this way(async () => { Promise.all([selectPizza(), selectDrink()].then(orderItems) // async call})()

登录后复制

我们将语句分成两个函数。在函数内部,每个语句都依赖于前一个语句的执行。然后我们同时执行这两个函数 selectPizza()和selectDrink() 。

在第二个例子中我们需要处理未知数量的 Promise。处理这个问题非常简单,我们只需要创建一个数组将所有 Promise 存入其中,使用 Promise.all() 方法并行执行:

async function orderItems() { const items = await getCartItems() // async call const noOfItems = items.length const promises = [] for(var i = 0; i < noOfItems; i++) { const orderPromise = sendRequest(items[i]) // async call promises.push(orderPromise) // sync call } await Promise.all(promises) // async call}

登录后复制

相信看了本文案例你已经掌握了方法,更多精彩请关注【创想鸟】其它相关文章!

推荐阅读:

React怎样在react-router路由实现登陆验证控制

Angular路由内路由守卫该如何使用

以上就是怎样处理async/await浪费性能问题的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2753534.html

(0)
上一篇 2025年3月8日 06:39:08
下一篇 2025年3月8日 06:39:14

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 如何操作node使用async 控制并发

    这次给大家带来如何操作node使用async 控制并发,操作node使用async 控制并发的注意事项有哪些,下面就是实战案例,一起来看一下。 目标 建立一个 lesson5 项目,在其中编写代码。 代码的入口是 app.js,当调用 no…

    2025年3月8日
    200
  • ES6中Async函数的详细介绍(附示例)

    本篇文章给大家带来的内容是关于es6中async函数的详细介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 async ES2017 标准引入了 async 函数,使得异步操作变得更加方便。 在异步处理上,as…

    2025年3月8日
    200
  • ES6下异步处理的实例讲解

    本篇文章给大家带来的内容是关于es6下异步处理的实例讲解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 前言 我们以查找指定目录下的最大文件为例,感受从 回调函数 -> Promise -> Generator…

    编程技术 2025年3月8日
    200
  • Node.js中的async如何使用

    Node.js中的async可以使用可读代码实现异步处理,异步处理是在更新之前和更新之后比较数据并且仅在页面更新时才传送数据的过程,这种异步处理有时在前端处理中称为Ajax。 Promise和async作为异步处理实现方法 可以使用prom…

    2025年3月8日
    200
  • Generator函数与async函数的区别介绍

    本篇文章给大家带来的内容是关于Generator函数与async函数的区别介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 Generator函数: Generator函数是ES2015提供的异步解决方案,与普通函数有很…

    编程技术 2025年3月8日
    200
  • JavaScript加载:defer与async

    页面的解析过程是单线程的,但是单线程亦可有同步与异步之分,script标签的解释方式分为3种,默认、defer和async三种 登录后复制登录后复制登录后复制登录后复制 默认模式,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 s…

    2025年3月8日
    200
  • JS 的 Promise 和 Async 详解

    因为 JavaScript 是单线程语言,所以同步代码一次只能执行一行。这就意味着同步代码的运行时间超过瞬间的话,它将停止其余代码的运行,直到完成运行为止。为了防止运行时间不确定的代码阻止其他代码的运行,我们需要使用异步代码。 Promis…

    2025年3月7日
    200
  • async/await的来龙去脉

    前言 在面试的时候,async/await是很能看出应试者知识面的一个点。当然自己也没想好从什么角度去阐释这个知识点。当面试管问的时候,你可以答自执行的generator的语法糖。但是自己有些过实现么,或者是看过他的实现。 babel是如何…

    编程技术 2025年3月7日
    200
  • 详解JavaScript里的await/async的作用和用法

    JavaScript里的await/async的作用和用法 分享:  await/async是ES7最重要特性之一,它是目前为止JS最佳的异步解决方案了。虽然没有在ES2016中录入,但很快就到来,目前已经在 ES-NextStage4阶段…

    2025年3月7日
    200
  • 使用async属性异步加载执行JavaScript的方法

    HTML5让我兴奋的一个最大的原因是,它里面实现的新功能和新特征都是我们长久以来一直期待的。比如,我以前一直在使用placeholders,但以前必须要用JavaScript实现。而HTML5里给JavaScript标记提供的async属性…

    2025年3月7日
    200

发表回复

登录后才能评论