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

相关文章

笔记本电脑屏幕模糊?6招恢复屏幕清晰!

在数字化时代的浪潮中,笔记本电脑已成为我们生活、学习和工作中不可或缺的一部分。然而,当那曾经清晰明亮的屏幕逐渐变得模糊不清时,无疑给我们的使用体验蒙上了一层阴影。屏幕模糊不仅影响视觉舒适度,更可能对我们的工作效率和眼睛健康构成威胁。 遇到笔记本电脑屏幕模糊的情况时我们应该如何解决?本文将与大家分享6个简单易懂的解决方法。 方法一:调整Windows分辨率 电脑屏幕模糊显示不清晰怎

个人博客文章目录索引(持续更新中...)

文章目录 一、Java基础二、Java相关三、MySql基础四、Mybatis基础及源码五、MybatisPlus基础六、Spring基础及源码七、Tomcat源码八、SpringMVC基础及源码   随着文章数量多起来,每次着急翻找半天,而是新申请的域名下来了,决定整理下最近几年的文章目录索引。(红色标记为常检索文章) 一、Java基础 1、Java基础(一):语言概述2、J

关于文章“python+百度语音识别+星火大模型+讯飞语音合成的语音助手”报错的修改

前言 关于我的文章:python+百度语音识别+星火大模型+讯飞语音合成的语音助手,运行不起来的问题 文章地址: https://blog.csdn.net/Phillip_xian/article/details/138195725?spm=1001.2014.3001.5501 1.报错问题 如果运行中报错,且报错位置在Xufi_Voice.py文件中的pcm_2_wav,如下图所示

Rust:Future、async 异步代码机制示例与分析

0. 异步、并发、并行、进程、协程概念梳理 Rust 的异步机制不是多线程或多进程,而是基于协程(或称为轻量级线程、微线程)的模型,这些协程可以在单个线程内并发执行。这种模型允许在单个线程中通过非阻塞的方式处理多个任务,从而实现高效的并发。 关于“并发”和“并行”的区别,这是两个经常被提及但含义不同的概念: 并发(Concurrency):指的是同时处理多个任务的能力,这些任务可能在同一时

Exception processing async thread queue Exception processing async thread queue

错误信息描述: eclipse 在debug中弹出异常信息框 Exception processing async thread queue Exception processing async thread queue 解决方法: eclipse 中有一个Expressions窗口,里面添加的 expression 没有正确执行,并且没有删除,只要 Remove All Expressio

将知乎专栏文章转换为 Markdown 文件保存到本地

一、参考内容 参考知乎文章`代码 | 将知乎专栏文章转换为 Markdown 文件保存到本地,利用代码为GitHub:https://github.com/chenluda/zhihu-download。 二、步骤 1.首先安装包flask、flask-cors、markdownify 2. 运行app.py 3.在浏览器中打开链接,并填写URL和Cookies 获取Cookies的步

一篇文章带你快速入门java

文章目录 一、一个简单的java代码1.1 Java程序的结构由三个不成组成:1.2 运行java程序1.3 JDK,JRE,JVM之间的关系?(面试题)1.4 标识符1.5 注释1.6 关键字 一、一个简单的java代码 public class HelloJava {public static void main(String[] args) {System.out.

警惕!推广文章与视频的兼职骗局大揭秘

在互联网时代,我们常常会看到各种各样的推广兼职信息,承诺可以轻松赚钱,特别是在推广文章和视频方面。然而,在这些看似诱人的机会背后,往往隐藏着一些骗局。本文将为大家揭示这些骗局,帮助大家避免上当受骗。 一、骗局特征 1. **高额回报承诺**:骗子常常以高额的回报作为诱饵,声称只要转发文章、分享视频,就能获得丰厚的佣金或收益。然而,这种不切实际的高额回报往往是骗局的开始。 2. **简单操作

(转)Sublime Text 2 (Emmet):HTML/CSS代码快速编写神器

Emmet的前身是大名鼎鼎的Zen coding,如果你从事Web前端开发的话,对该插件一定不会陌生。它使用仿CSS选择器的语法来生成代码,大大提高了HTML/CSS代码编写的速度,比如下面的演示:   Zen coding下的编码演示   去年年底,该插件已经改名为Emmet。但Emmet不只改名,还带来了一些新特性。本文就来直观地演示给你。 一、快速编写HTML代码 1.

玩转Web之easyui(二)-----easy ui 异步加载生成树节点(Tree),点击树生成tab(选项卡)

关于easy ui 异步加载生成树及点击树生成选项卡,这里直接给出代码,重点部分代码中均有注释 前台: $('#tree').tree({ url: '../servlet/School_Tree?id=-1', //向后台传送id,获取根节点lines:true,onBeforeExpand:function(node,param){ $('#tree').tree('options'