什么是async/await地狱?
在JavaScript中,async/await
语法为我们处理异步代码提供了一种更直观、更易读的方式,如果滥用或不正确使用,可能会导致“async/await地狱”,即代码变得冗长且难以维护,这种情况通常发生在开发者将每个异步操作都串行化,即使这些操作本可以并行执行。
async/await地狱的示例
假设我们要编写一个购买披萨和饮料的程序,以下是一个典型的async/await地狱的例子:
(async () => { const pizzaData = await getPizzaData(); // 获取披萨列表(异步调用) const drinkData = await getDrinkData(); // 获取饮料列表(异步调用) const chosenPizza = choosePizza(); // 选择披萨(同步调用) const chosenDrink = chooseDrink(); // 选择饮料(同步调用) await addPizzaToCart(chosenPizza); // 将选中的披萨加入购物车(异步调用) await addDrinkToCart(chosenDrink); // 将选中的饮料加入购物车(异步调用) orderItems(); // 确认订单(异步调用) })();
这段代码虽然能够运行,但并不是一个好的实现方式,问题在于,所有的代码都是一行接着一行执行的,没有任何并发执行的情况,为什么在获取饮料列表之前需要等待披萨列表的返回?我们应该尝试同时获取饮料和披萨的列表。
如何避免async/await地狱
找出所有依赖其他代码来执行的代码
在我们的例子中,选择披萨和饮料的操作是相互独立的,可以并行进行,我们可以将这些操作分成不同的异步函数,并利用Promise.all()方法来并发执行它们。
把相互依赖执行的语句整合在异步函数里面
选择披萨需要以下几个互相依赖的语句:获取披萨列表、选择其中一个披萨以及添加到购物车中,我们应该把这些语句整合在一个异步函数里面,同样地,选择饮料的操作也放在另一个异步函数里。
并发的执行这些异步函数
我们将利用事件循环的优势来并发地执行这些非阻塞异步函数,常用的方法是先返回Promise然后使用Promise.all()方法。
修改后的代码示例
async function selectPizza() { const pizzaData = await getPizzaData(); // 获取披萨列表(异步调用) const chosenPizza = choosePizza(); // 选择披萨(同步调用) await addPizzaToCart(chosenPizza); // 将选中的披萨加入购物车(异步调用) } async function selectDrink() { const drinkData = await getDrinkData(); // 获取饮料列表(异步调用) const chosenDrink = chooseDrink(); // 选择饮料(同步调用) await addDrinkToCart(chosenDrink); // 将选中的饮料加入购物车(异步调用) } (async () => { const [pizzaPromise, drinkPromise] = Promise.all([selectPizza(), selectDrink()]); await pizzaPromise; await drinkPromise; orderItems(); // 确认订单(异步调用) })();
在这个修改后的示例中,我们首先定义了两个异步函数selectPizza
和selectDrink
,分别负责选择披萨和饮料的相关操作,在主函数中使用Promise.all()方法并发地执行这两个异步函数,最后等待它们完成并确认订单,这样不仅提高了代码的性能,还使其更加清晰易读。
相关问题与解答
问题1:如果我们忘记了await关键字会怎样?
如果在调用异步函数时忘记使用await
关键字,这意味着函数开始执行了,但不会等待其完成,异步函数会返回一个Promise对象,这个Promise可以在之后被解析,另一个后果是编译器不知道你需要等待这个函数执行完成,因此编译器可能会在异步任务还没有完成的时候退出程序,我们需要使用await
关键字来确保程序在适当的时候等待异步函数完成。
问题2:如何在多个异步操作之间实现并发执行?
要在多个异步操作之间实现并发执行,可以使用Promise.all()方法,这个方法接受一个包含多个Promise对象的数组作为参数,并返回一个新的Promise,当所有的输入Promise都成功解决时,新的Promise也会成功解决,并且解决的值是一个包含所有输入Promise解决值的数组,通过这种方式,我们可以并发地执行多个异步操作,而不需要等待前一个操作完成再进行下一个操作。
以上就是关于“async/await地狱避免”的问题,朋友们可以点击主页了解更多内容,希望可以够帮助大家!
原创文章,作者:K-seo,如若转载,请注明出处:https://www.kdun.cn/ask/645120.html