async await -- js异步最终解决方案

在 JS 中说到异步,我们肯定能想到最简单的异步方式–回调,和在 Promise 规范;这里,我们就不在说什么函数的回调了,直接说 Promise ,让我们回顾一下 Promise

如果对 Promise 不了解,请自行百度,或者看我的另一篇博客:ES6中的Promis的使用方法

1. Promise简介

这里我们就再啰嗦的介绍一下 Promise 对象

Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及其返回的值。

Promise 对象是由关键字 new 及其构造函数来创建的。构造函数会把一个叫做“处理器函数”(executor function)的函数作为它的参数。这个“处理器函数”接受两个函数 resolvereject 作为其参数。当异步任务顺利完成且返回结果值时,会调用 resolve 函数,而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用 reject 函数。

Promise 状态:

  • pending:初始状态,既不是成功,也不是失败状态
  • fulfilled:操作成功
  • rejected:操作失败

让我们看一个 Promise 的例子:

function division(fdiv, div) {
	return new Promise(function(resolve, reject) {
		// 使用延时函数,模拟异步
		setTimeout(() => {
			if(div === 0) {
				// 模拟异常
				reject('0不能作为除数!!!')
			} else {
				// 模拟正常
				resolve(fdiv / div);
			}
		}, 5000);
	});
}

var pms = division(100, 10);
pms.then(res => {
	console.log(res);
	// 10
}).catch(err => {
	console.log(err);
})

console.log(pms);
// Promise {<resolved>: 10}

通过 then 传递执行成功和失败的方法,或者统一使用 catch 单独捕捉失败;并且 then 支持链式反映,可以无限连接then ,但是上一个 then 必须要返回Promise 对象,并且可以使用 catch 统一捕获异常。

2. 如何理解async、await

async 即“异步”,而 await 为“等待”;这样就很好理解了,async 用来声明一个异步操作的方法(async function 方法名),而 await 用于等待一个异步任务执行完成。

这里需要注意:await 只能出现在 async 函数中

让我们修改一项上面的demo,使用 asyncawait 完成吧:

function division(fdiv, div) {
	return new Promise(function(resolve, reject) {
		// 使用延时函数,模拟异步
		setTimeout(() => {
			if(div === 0) {
				// 模拟异常
				reject('0不能作为除数!!!')
			} else {
				// 模拟正常
				resolve(fdiv / div);
			}
		}, 5000);
	});
}

async function test(x, y) {
	try {
		const rtn = await division(x, y);
		console.log(rtn);
	} catch(e) {
		// 经过测试,我们可以发现,当走异常的时候,我们可以使用try...catch...进行异常捕捉
		console.log(e);
	}
}

test(100, 10);				// 10					在try中打印
test(100, 0);				// 0不能作为除数!!!		在catch中打印

3. async、await如何执行

async 声明方法为异步操作,await 是一个操作符,即 await 后面是一个表达式。

async 的返回值:

async function test(fdiv, div) {
	if(div === 0) {
		throw "0不能为除数!!!";
	} else {
		return fdiv / div
	}
}


console.log(test(100, 10));
// Promise {<resolved>: 10}
console.log(test(100, 0));
// Promise {<rejected>: "0不能为除数!!!"}
// Uncaught (in promise) 0不能为除数!!!

从上面可以看出,当调用一个 async 函数时,会返回一个 Promise 对象。根据mdn的解释:

  • 当这个 async 函数返回一个值时,Promiseresolve 方法会负责传递这个值;
  • async 函数抛出异常时,Promisereject 方法也会传递这个异常值。async 函数中可能会有 await 表达式,await 表达式会使 async 函数暂停执行,直到表达式中的 Promise 解析完成后继续执行 asyncawait 后面的代码并返回解决结果。

注意: await 关键字仅仅在 async function中有效

既然返回的是 Promise 对象,那么如果在外层不能使用 await 关键字获取的情况下,我们就可以使用 then 链来处理解过了:

async function test(fdiv, div) {
	if(div === 0) {
		throw "0不能为除数!!!";
	} else {
		return fdiv / div
	}
}

// 使用then链处理结果
test(100, 10).then(res => {
	console.log(res);
}).catch(err => {
	console.log(err);
});

那么如果 async 函数没有返回值,又会怎么样呢;这个很容一想到,因为方法没有返回值得时候,如果声明变量接受,则接收到的值为 undefined;所以他会返回:Promise.resolve(undefined)

既然 async 和 `` 基本上和 Promise 相似,但是他们有没有区别呢;这里还是有一点区别的,如下:

function division(fdiv, div) {
	return new Promise(function(resolve, reject) {
		// 使用延时函数,模拟异步
		setTimeout(() => {
			if(div === 0) {
				// 模拟异常
				reject('0不能作为除数!!!')
			} else {
				// 模拟正常
				resolve(fdiv / div);
			}
		}, 5000);
	});
}

// 使用await方式实现
async function test1() {
	const t = await division(100, 10);
	console.log(t);
	// 这句代码必须等待await执行完成后,才能执行
	console.log("执行这句话")
}

// 使用Promise方式实现
function test2() {
	division(100, 10).then(res => {
		console.log(res);
	});
	// 这句代码不用等到then执行完成,就还立刻执行
	console.log("执行这句话")
}

test1();
test2();

区别就是这样的,大家根据场景的不同,进行选择使用吧!

4. await 操作符

MDN 是这样描述 await 的:

await 表达式会暂停当前 async function 的执行,等待 Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行async function。若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出。另外,如果 await 操作符后的表达式的值不是一个 Promise,则返回该值本身。

起始简单说就是:

async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。

按照mdn解释 await 会暂停当前 async 函数执行,并且 await 后面是一个表达式,即这个 await 等待的是一个表达式(这个表达式返回promise 对象或者一个具体的值):

  • 假如这个表达式如果返回的是一个 Promise 对象, 那么它的返回值,实际上就是 Promise 的回调函数 resolve 的参数,如果这个 Promise rejected 了,await 表达式会把 Promise 的异常抛出。
  • 假如这个表达式如果返回的是一个常量,那么会把这个常量转为 Promise.resolve(xx),同理如果没有返回值也是Promise.resolve(underfind)

这里不在列举更多的例子,上面的例子已经包含了,我想表达的一切。

5. 总结

  • async 用来声明方法是异步方法
  • awiat 用于 async 方法之中,用来暂停方法的执行,等待后面表达式给出结果,然后继续执行方法
  • async 函数的返回结果为一个 Promise 对象;当 async 函数返回一个值的时候,就等于 Promise 调用 resolve 函数;当 async 函数抛出异常的时候,就等于 Promise 调用 reject 函数。
  • await 操作符用于等待一个 Promise 对象,并将 Promise 的结果进行转换(成功则将其 resolve 中的结果作为返回值,失败则抛出异常,将 reject 中的值作为异常信息);如果 await 后面不是 Promise 对象,则会被转换为 Promise.resolve(xx)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值