async 与 await(JavaScript)

目录捏


前言

async / awaitES2017(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 中返回的内容( resolvereject 的参数),并会阻塞该函数内后面的代码直到获取到返回值后语句才会往下执行;若不是 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/awaitPromise 并不存在谁代替谁的说法,因为 async/await 是寄生于 Promise、Generater 的语法糖。使用 async/await 可以实现用同步代码的风格来编写异步代码,而异步编程的最高境界就是不关心它是否是异步,async/await 很好的解决了这一点。

相关推荐
道不尽世间的沧桑21 分钟前
第17篇:网络请求与Axios集成
开发语言·前端·javascript
久绊A29 分钟前
Python 基本语法的详细解释
开发语言·windows·python
diemeng11191 小时前
AI前端开发技能变革时代:效率与创新的新范式
前端·人工智能
bin91533 小时前
DeepSeek 助力 Vue 开发:打造丝滑的复制到剪贴板(Copy to Clipboard)
前端·javascript·vue.js·ecmascript·deepseek
软件黑马王子4 小时前
C#初级教程(4)——流程控制:从基础到实践
开发语言·c#
闲猫4 小时前
go orm GORM
开发语言·后端·golang
晴空万里藏片云5 小时前
elment Table多级表头固定列后,合计行错位显示问题解决
前端·javascript·vue.js
曦月合一5 小时前
html中iframe标签 隐藏滚动条
前端·html·iframe
奶球不是球5 小时前
el-button按钮的loading状态设置
前端·javascript
kidding7235 小时前
前端VUE3的面试题
前端·typescript·compositionapi·fragment·teleport·suspense