async 与 await(JavaScript)

目录捏


前言

async / await 是 ES2017(ES8) 提出的基于 Promise 解决异步的最终方案。上一篇文章介绍了 回调地狱 与 Promise(JavaScript),因为 Promise 的编程模型依然充斥着大量的 then 方法,其虽然解决了回调地狱的问题,但是在语义化及代码可读性方面依然存在缺陷,这就是 async / await 出现的原因。


一、async

  • async(异步) :用来声明一个异步函数;await(async wait):用来等待异步函数执行
  • async 是一个加在函数前的修饰符,被 async 定义的函数会默认返回一个 Promise 对象 resolve 的值,因此对 async 函数可以直接使用 then 方法
javascript 复制代码
   // 默认返回 Promise 对象成功值
   async function fun() {
       console.log('用户数据读取中~~');
       return '用户数据读取成功!!';
   }
   fun().then(val => {
       console.log(val)
   })
javascript 复制代码
	// 根据 Promise 对象决定返回值
	async function fun() {
	    console.log('用户数据读取中~~')
	    return new Promise((resolve, reject) => {
	        setTimeout(() => {
	            resolve('用户数据读取成功!!')
	        }, 3000)
	    })
	}
	
	fun().then(value => {
	    console.log(value)
	})
	
	console.log(1);
	console.log(2);
	console.log(3);

二、await

若单有 async,则和 Promise 功能相似,但配合上 await 则效果完全不同

  • await 也是一个修饰符,只能放在 async 定义的函数内
  • await 修饰的若是 Promise 对象:可获取 Promise 中返回的内容( resolve 或 reject 的参数),并会阻塞该函数内后面的代码直到获取到返回值后语句才会往下执行;若不是 Promise 对象:将此非 Promise 的语句当做 await 表达式的结果
javascript 复制代码
	 // 非 Promise 对象
	 async function fun() {
	     console.log('用户数据读取中~~');
	     let a = await '用户数据读取成功!!';
	     console.log(a);
	 }
	 fun()
javascript 复制代码
	async function fun() {
	    console.log('用户数据读取中~~')
	    console.log(1);
	    console.log(2);
	    console.log(3);
	    // Promise 对象
	    let a = await new Promise((resolve, reject) => {
	        setTimeout(() => {
	            resolve('用户数据读取成功!!')
	        }, 3000)
	    })
	    console.log(a);
	}
	
	fun()
javascript 复制代码
	async function fun() {
	    let a = await 768
	    console.log(a)
	    let b = await '用户数据读取中...'
	    console.log(b)
	    // 注意:此处等待对象为函数,故需通过()调用
	    let c = await function () {
	        return '预计时间:3s'
	    }()
	    console.log(c)
	    let d = await new Promise((resolve, reject) => {
	        setTimeout(function () {
	            resolve('用户数据读取成功!!')
	        }, 3000)
	    })
	    console.log(d)
	}
	
	fun()

由以上案例可知 await 不仅可以用于等 Promise 对象,还可以等任意表达式,即 await 后面实际是可以接普通函数调用或者直接量的。不过我们更多的是放一个返回 Promise 对象的表达式,它等待的是 Promise 对象执行完毕所返回的结果。

javascript 复制代码
	 // 非 Promise 对象
	function notPromise(time) {
	    setTimeout(() => {
	        console.log(time);
	        return 1;
	    }, time)
	}
	
	async function fun() {
		// 将 notPromise 所执行语句当做 await 表达式的结果
	    let a = await notPromise(3000);
	    let b = notPromise(2000);
	    let c = await notPromise(1000);
	    console.log(a);
	    console.log('先执行我捏~')
	}
	
	fun();

三、使用方法

javascript 复制代码
	// 定义一个异步函数,time秒后才能获取到值
	function fun(time) {
		// Promise 对象
	    return new Promise((resolve, reject) => {
	        setTimeout(() => {
	            resolve('用户数据读取成功!!')
	        }, time)
	    })
	}
	
	async function test() {
	    console.log(1);
	    console.log(2);
	    console.log(3);
	    // 获取到 Promise 对象所返回的结果( resolve参数 )
	    let a = await fun(3000);
	    console.log(a)
	}
	
	test()

上一篇文章 回调地狱 与 Promise(JavaScript)中通过 Promise 解决了回调地狱问题,但不断地调用 then 链使代码看起来十分冗余从而导致可读性变差,故本文通过 asysc 与 await 来简化上文代码。

**问题回顾:**分别间隔 3s、2s、1s 按顺序输出:我在定时器1里捏!!,我在定时器2里捏!!,我在定时器3里捏!!

await 的优势在于简化处理 then 链,使 异步代码 的书写方式更接近于 同步代码

javascript 复制代码
	function promise(value, time) {
	    return new Promise((resolve, reject) => {
	        setTimeout(() => {
	            resolve(value)
	        }, time)
	    })
	}
	
	async function fun() {
	    let a = await promise('我在定时器1里捏!!', 3000)
	    console.log(a);
	    let b = await promise('我在定时器2里捏!!', 2000)
	    console.log(b);
	    let c = await promise('我在定时器3里捏!!', 1000)
	    console.log(c);
	}
	
	fun()

总结

最后我们可以通过三张图片来直观对比一下三种写法:

1.回调地狱

2.Promise

3.async + await

注意

  • await 必须写在 async 函数中, 但 async 函数中可以没有 await
  • 在使用 await 的时候我们只是暂停了函数,而非整段代码

async/await 与 Promise 并不存在谁代替谁的说法,因为 async/await 是寄生于 Promise、Generater 的语法糖。使用 async/await 可以实现用同步代码的风格来编写异步代码,而异步编程的最高境界就是不关心它是否是异步,async/await 很好的解决了这一点。

相关推荐
benchmark_cc38 分钟前
Python 量化系统如何设计统一的数据访问接口:从策略解耦到数据层架构
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
程序员老赵1 小时前
Docker 部署青龙面板:轻松搭建定时任务管理平台
前端·docker·开源
Swot1 小时前
Asciidoctor 公式数字下标错位问题:原因分析与解决方案
前端
Swot1 小时前
leo-editor 中将 Markdown 内容转成 asciidoc 格式
前端
const_qiu1 小时前
第四章 00:开篇 —— 从「会聊天」到「记得住、会干活、能协作」
java·开发语言·人工智能·python
Wang's Blog1 小时前
Java 项目实战: 交友项目 - 个人资料管理的更新接口实现与坑
java·开发语言·交友
狒狒AI1 小时前
Remotion / GSAP+Three / HyperFrames / Skia 四栈实测:代码渲染知识视频的选栈方法(附开源技能)
前端·人工智能·aigc
修炼的dance1 小时前
浏览器里导出H.265,8.5秒和55.5秒差在硬件
前端
补码缩写1 小时前
WebCodecs选编码器,探测之后还要验解码和播放
前端
大文说跨境1 小时前
亚马逊多账号管理浏览器怎么选?云登/紫鸟/AdsPower 对比
java·前端·自动化