ES7:异步神器async-await(我看过讲得最清晰透彻的文章)

2024-04-02 15:58

本文主要是介绍ES7:异步神器async-await(我看过讲得最清晰透彻的文章),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景:

关于异步处理,ES5的回调使我们陷入地狱,ES6Promise使我们脱离魔障,终于、ES7async-await带我们走向光明。今天就来学习一下 async-await

async-await和Promise的关系

经常会看到有了 async-await、promise 还有必要学习吗、async await优于promise的几个特点,接收了这些信息后,就蒙圈了。现在才知道,async-awaitpromise和generator的语法糖。只是为了让我们书写代码时更加流畅,当然也增强了代码的可读性。简单来说:async-await 是建立在 promise机制之上的,并不能取代其地位。

基本语法

async function basicDemo() {let result = await Math.random();console.log(result);
}basicDemo();
// 0.6484863241051226
//Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}

上述代码就是async-await的基本使用形式。有两个陌生的关键字async、await,同时函数执行结果似乎返回了一个promise对象。

await

await 可以理解为是 async wait 的简写。await 必须出现在 async 函数内部,不能单独使用。

function notAsyncFunc() {await Math.random();
}
notAsyncFunc();//Uncaught SyntaxError: Unexpected identifier

await 后面可以跟任何的JS 表达式。虽然说 await 可以等很多类型的东西,但是它最主要的意图是用来等待 Promise 对象的状态被 resolved。如果await的是 promise对象会造成异步函数停止执行并且等待 promise 的解决,如果等的是正常的表达式则立即执行。

function sleep(second) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(' enough sleep~');}, second);})
}
function normalFunc() {console.log('normalFunc');
}
async function awaitDemo() {await normalFunc();console.log('something, ~~');let result = await sleep(2000);console.log(result);// 两秒之后会被打印出来
}
awaitDemo();
// normalFunc
// VM4036:13 something, ~~
// VM4036:15  enough sleep~

希望通过上面的 demo,大家可以理解我上面的话。

实例

举例说明啊,你有三个请求需要发生,第三个请求是依赖于第二个请求的解构第二个请求依赖于第一个请求的结果。若用 ES5实现会有3层的回调,若用Promise 实现至少需要3个then。一个是代码横向发展,另一个是纵向发展。今天指给出 async-await 的实现哈~

//我们仍然使用 setTimeout 来模拟异步请求
function sleep(second, param) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(param);}, second);})
}async function test() {let result1 = await sleep(2000, 'req01');let result2 = await sleep(1000, 'req02' + result1);let result3 = await sleep(500, 'req03' + result2);console.log(`${result3}${result2}${result1}`);
}test();
//req03req02req01
//req02req01
//req01

错误处理

上述的代码好像给的都是resolve的情况,那么reject的时候我们该如何处理呢?

function sleep(second) {return new Promise((resolve, reject) => {setTimeout(() => {reject('want to sleep~');}, second);})
}async function errorDemo() {let result = await sleep(1000);console.log(result);
}
errorDemo();// VM706:11 Uncaught (in promise) want to sleep~// 为了处理Promise.reject 的情况我们应该将代码块用 try catch 包裹一下
async function errorDemoSuper() {try {let result = await sleep(1000);console.log(result);} catch (err) {console.log(err);}
}errorDemoSuper();// want to sleep~
// 有了 try catch 之后我们就能够拿到 Promise.reject 回来的数据了。

小心你的并行处理!!!

我这里为啥加了三个感叹号呢~,因为对于初学者来说一不小心就将 ajax 的并发请求发成了阻塞式同步的操作了,我就真真切切的在工作中写了这样的代码。await 若等待的是 promise 就会停止下来。业务是这样的,我有三个异步请求需要发送,相互没有关联,只是需要当请求都结束后将界面的 loading 清除掉即可。
刚学完 async await 开心啊,到处乱用~

function sleep(second) {return new Promise((resolve, reject) => {setTimeout(() => {resolve('request done! ' + Math.random());}, second);})
}async function bugDemo() {await sleep(1000);await sleep(1000);await sleep(1000);console.log('clear the loading~');
}bugDemo();

loading 确实是等待请求都结束完才清除的。但是你认真的观察下浏览器的 timeline 请求是一个结束后再发另一个的(若观察效果请发真实的 ajax 请求)
那么,正常的处理是怎样的呢?

async function correctDemo() {let p1 = sleep(1000);let p2 = sleep(1000);let p3 = sleep(1000);await Promise.all([p1, p2, p3]);console.log('clear the loading~');
}
correctDemo();// clear the loading~

恩, 完美。看吧~ async-await并不能取代promise.

await in for 循环

最后一点了,await必须在async函数的上下文中的。

// 正常 for 循环
async function forDemo() {let arr = [1, 2, 3, 4, 5];for (let i = 0; i < arr.length; i ++) {await arr[i];}
}
forDemo();//正常输出
// 因为想要炫技把 for循环写成下面这样
async function forBugDemo() {let arr = [1, 2, 3, 4, 5];arr.forEach(item => {await item;});
}
forBugDemo();// Uncaught SyntaxError: Unexpected identifier

for内使用await不会报错(因为for不是函数),在forEach里报错了,意为即使在async函数内包其它函数,也不能在该函数内使用await,可以理解为演示作用域。

综上,希望大家看了能得到帮助和提升!请带着原因指正和批评,多谢

这篇关于ES7:异步神器async-await(我看过讲得最清晰透彻的文章)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/870415

相关文章

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Java 中实现异步的多种方式

《Java中实现异步的多种方式》文章介绍了Java中实现异步处理的几种常见方式,每种方式都有其特点和适用场景,通过选择合适的异步处理方式,可以提高程序的性能和可维护性,感兴趣的朋友一起看看吧... 目录1. 线程池(ExecutorService)2. CompletableFuture3. ForkJoi

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

Spring Boot 中正确地在异步线程中使用 HttpServletRequest的方法

《SpringBoot中正确地在异步线程中使用HttpServletRequest的方法》文章讨论了在SpringBoot中如何在异步线程中正确使用HttpServletRequest的问题,... 目录前言一、问题的来源:为什么异步线程中无法访问 HttpServletRequest?1. 请求上下文与线

在 Spring Boot 中使用异步线程时的 HttpServletRequest 复用问题记录

《在SpringBoot中使用异步线程时的HttpServletRequest复用问题记录》文章讨论了在SpringBoot中使用异步线程时,由于HttpServletRequest复用导致... 目录一、问题描述:异步线程操作导致请求复用时 Cookie 解析失败1. 场景背景2. 问题根源二、问题详细分

Java对象和JSON字符串之间的转换方法(全网最清晰)

《Java对象和JSON字符串之间的转换方法(全网最清晰)》:本文主要介绍如何在Java中使用Jackson库将对象转换为JSON字符串,并提供了一个简单的工具类示例,该工具类支持基本的转换功能,... 目录前言1. 引入 Jackson 依赖2. 创建 jsON 工具类3. 使用示例转换 Java 对象为

Java中将异步调用转为同步的五种实现方法

《Java中将异步调用转为同步的五种实现方法》本文介绍了将异步调用转为同步阻塞模式的五种方法:wait/notify、ReentrantLock+Condition、Future、CountDownL... 目录异步与同步的核心区别方法一:使用wait/notify + synchronized代码示例关键

springboot的调度服务与异步服务使用详解

《springboot的调度服务与异步服务使用详解》本文主要介绍了Java的ScheduledExecutorService接口和SpringBoot中如何使用调度线程池,包括核心参数、创建方式、自定... 目录1.调度服务1.1.JDK之ScheduledExecutorService1.2.spring

异步线程traceId如何实现传递

《异步线程traceId如何实现传递》文章介绍了如何在异步请求中传递traceId,通过重写ThreadPoolTaskExecutor的方法和实现TaskDecorator接口来增强线程池,确保异步... 目录前言重写ThreadPoolTaskExecutor中方法线程池增强总结前言在日常问题排查中,

一文详解Java Condition的await和signal等待通知机制

《一文详解JavaCondition的await和signal等待通知机制》这篇文章主要为大家详细介绍了JavaCondition的await和signal等待通知机制的相关知识,文中的示例代码讲... 目录1. Condition的核心方法2. 使用场景与优势3. 使用流程与规范基本模板生产者-消费者示例