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 很好的解决了这一点。

相关推荐
博客zhu虎康3 分钟前
ElementUI 的 form 表单校验
前端·javascript·elementui
蜗牛hb4 分钟前
VMware Workstation虚拟机网络模式
开发语言·学习·php
汤姆和杰瑞在瑞士吃糯米粑粑19 分钟前
【C++学习篇】AVL树
开发语言·c++·学习
cronaldo9124 分钟前
研发效能DevOps: Vite 使用 Element Plus
vue.js·vue·devops
Biomamba生信基地26 分钟前
R语言基础| 功效分析
开发语言·python·r语言·医药
手可摘星河28 分钟前
php中 cli和cgi的区别
开发语言·php
敲啊敲952731 分钟前
5.npm包
前端·npm·node.js
CodeClimb41 分钟前
【华为OD-E卷-木板 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
咸鱼翻面儿1 小时前
Javascript异步,这次我真弄懂了!!!
javascript
brrdg_sefg1 小时前
Rust 在前端基建中的使用
前端·rust·状态模式