async函数

本文深入探讨ES6中async函数的使用,包括其语法特点、如何处理异步操作及错误捕获,对比传统异步解决方案如回调函数和Promise,展示async函数在代码简洁性和可读性上的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

es6中引入的async函数为开发者提供了一种功能更加强大方便的异步操作方案。

1.1

创建async函数与普通函数的区别就是,async函数需要使用async关键字进行创建。async就是异步的意思。

function a () {

	return new Promise((resolve,reject) => {

		setTimeout(() => resolve('2'), 1000);
	})
}


async function fn () {

	let p = await a();

	console.log(p)

}

fn() //2

上面的例子中,会在1秒钟之后打印出2。
先看a函数,a函数里面返回了一个promise对象,在一秒钟之后,会把promise设置为成功的状态。
在下面,我们又创建了一个async函数,在async函数中,可以看到一个await关键字,await就是等待的意思。这里的效果是,会等待a函数中返回的promise对象的状态为成功时,才会继续执行函数体内下面的代码。(async函数体外的代码不受影响),所以一秒钟之后打印出了2。
await关键字右边应该是一promise对象,如果不是,会被转换成一个立即resolve的promise对象。
由此你会发现,async函数体内的异步操作变得像是同步的一样,想想回调函数的回调地狱,或者单纯使用promise,那种then方法的链式调用。async函数的方式是不是更加简便呢?我们可以来看这三种方式的例子。

比如我们需要完成三个表单的验证,第一个验证完毕后才能进行下一个表单的验证。

回调函数式:

function fn1 () {
	//发起第一个表单的验证,验证成功后发起第二个表单的验证
	function fn2 () {
		//完成第二个表单的验证后,发起第三个表单的验证
		function fn3 () {

		}
	}
}

promise方式:

fn1() //第一个表单验证成功
.then(res => fn2()) //第二个表单验证成功
.then(res => fn3()) //第三个表单验证成功

async函数方式:

async function func () {
	
	await fn1();
	await fn2();
	await fn3();
}

1.2

async函数会返回一个promise对象。因此可以是以then方式添加回调。async函数内部返回的值,会作为参数传递给then方法中的回调函数。

function a () {

	return new Promise((resolve,reject) => {

		setTimeout(() => resolve(2), 1000);
	})
}


async function fn () {

	let p = await a();

	return p+1;

}

fn().then(res => console.log(res))	//3

需要注意的是,async函数返回的promise对象必须等待函数内部的所有await后面的promise对象的状态都改变为resolve的时候,自身的状态才会改变为resolvue,然后执行then方法中的回调。
如果是遇到return语句的时候,对象的状态会立即改变。当抛出错误,或者其中一个await后面的promise对象状态变更为reject,那么async函数返回的promise对象的状态会被立即设置为reject状态。对抛出的错误对象,可以通过catch方法中的回调进行接收。如下:

async function fn () {

throw new Error('出错了');

}

fn().catch(err => console.log(err))  //出错了

只要有一个await命令后面的promise的状态变为reject,那么整个async函数都会中断执行,并且reject的参数会被catch方法中的回调函数接收。

function a () {

	return new Promise((resolve,reject) => {

		setTimeout(() => reject('失败了'), 1000);
	})
}


async function fn () {

	await a();
	console.log(1)//不执行

}

fn().catch(err => console.log(err)) //失败了

上面的代码中,由于a函数中返回的promise对象的状态是失败的,导致后面的代码不执行,而reject的参数被catch函数中的回调函数接受到,打印出失败了。

如果不希望因为上一个promise对象状态的失败导致后面的代码不执行。可以把代码放在try,catch语句里。

function a () {

	return new Promise((resolve,reject) => {

		setTimeout(() => reject('失败了'), 1000);
	})
}


async function fn () {

	try {
		await a();
	}catch(e) {
		console.log(e)//失败了
	}
	console.log(1)//1

}

fn()

上面代码中,try、catch语句中的promise的reject的参数被catch接受到,并且后面的代码没有中断,依旧执行。下面是抛出错误的情况下:

function a () {

	return new Promise((resolve,reject) => {
		throw new Error('出错了');
	})
}


async function fn () {

		try {
			await a();
		}catch (e) {
			console.log(e) //出错了
		}
		console.log(1) //1
}

fn()

1.3 注意不要将没有依赖关系的异步任务写成继发的方式。

async function fn () {

		await fn1();
		await fn2();
}

上面函数中的fn1和fn2异步任务没有依赖关系,但被写成继发的方式,因为只有fn1的promise状态改变了,后面的代码才能运行,所以,这两个异步任务应当改成同时出发。

方式一:

async function fn () {

		let [a,b] = Promise.all( [fn1(), fn2()] );
}

方式二:

async function fn () {
	
	let a = await fn1();
	let b = await fn2();

	let f1 = await a;
	let f2 = await b;
		
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值