aysnc 函数

async 函数

概念

是 Generator 函数(生成器函数)的语法糖。

特点

与 Generator 函数的改进体现在:

1,内置执行器

2,更好的语义

async 和 await 比起星号和 yield ,语义更清楚。async 表示函数有异步操作,await 表示紧跟在后面的表达式需要等待结果

3,更广的适用性

co 模块规定,yield 命令后面只能是 Thunk 函数或者 Promise 对象,而 async 函数的 await 命令后面可以是 Promise 对象,和原始类型值(数值,字符串和布尔值,但这时等于同步操作)。

4,返回的是 Promise 对象

比 Generator 函数的返回值 是 Iterator 对象更方便。可以用 then 方法指定下一步操作。

async 函数完全可以看做是由多个异步操作包装成一个 Promise 对象,而 await 命令就是 内部 then 命令的语法糖。

语法

async 函数的语法规则总体上来说比较简单,难点在于错误处理机制。

返回 Promise对象

async 函数返回一个 Promise 对象,内部的 return 语句返回的值,会成为 then 方法回调函数的参数。

async function fn() {
		return 'hello world';
	}
	fn().then( v => {
		console.log(v);
	})

async 函数内部抛出错误会导致返回的 Promise 对象变成 reject 转态。抛出的错误对象会被 catch 方法回调函数接收。

async function fn() {
		throw new Error('出错了!');
	}
	fn().then( 
	  success => console.log(success),
	  error => console.log(error)
	)

Promise 对象的状态变化

async 函数返回的 Promise 对象必须等到内部所有 await 命令后面的 Promise 对象执行完才会发生状态改变,除非遇到 return 语句或者抛出错误。也就是说,只有 async 函数内部的异步操作执行完成,或者发生错误,才会执行 then 方法指定的回调函数。

async function getTitle(url) {
		let response = await fetch(url);
		let html = awaiit response.text();
		return html.match(/<title>([\s\S])</title>/)[1];
	}
	getTitle('www.baidu.com').then(v => console.log(v));

上述代码,函数 getTitle() 内部有三个 操作:抓取网页,取出文本,匹配页面标题。只有这 3个 操作全部完成,才会执行 then 方法里面的 console.log()

await 命令

正常情况下,await 命令后面是一个 Promise 对象,如果不是,会被转成一个立即 resolve 的 Promise 对象。

async function fn() {
		return await 123;
	}
	fn().then(v => console.log(v)); //123

await 命令后面的 Promise 对象如果变成 reject 状态,则 reject 的参数会被 catch 方法的回调函数接收到。

async function fn() {
		return await Promise.reject('出错了!');
	}
	fn().then(v => console.log(v))
	.catch(err => console.log(err))

只要有一个 await 语句后面的 Promise 变成 reject,那么整个 async 函数都会中断执行。

async function fn() {
		return await Promise.reject('出错了!');
		await Promise.resolve('hello world'); // 不会执行
	}
	fn().then(v => console.log(v))
	.catch(err => console.log("err =>", err))

错误处理

如果 await 命令后面的异步操作出错,那么等同于 async 函数返回的 Promise 对象被 reject 。

async function fn() {
		return await new Promise((resolve, reject) => {
			throw new Error('异步操作出错了');
		})
	}
	fn().then(v => console.log(v))
	.catch(err => console.log("err =>", err))

防止出错的方法也是将其放到 try ... catch 代码中。

async function fn() {
		try{
			await new Promise((resolve, reject) => {
				throw new Error('异步操作出错了');
			})
		}catch(e){
			//TODO handle the exception
		}
		return await('hello world');
	}
	fn().then(v => console.log(v))
	.catch(err => console.log("err =>", err))

如果有多个 await 命令,则可以统一放在 try ... catch 结构中。

 用法

当函数执行的时候,一旦遇到 await 就会先返回,等到异步操作完成,再接着执行函数体后面的语句。async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。

例子:

async function getStockPriceByName(name) {
		let symbol = await getStockSymbol(name);
		let price = await getStockPrice(symbol);
		return price;
	}
	getStockByName('good').then(function(result) {
		console.log(result);
	})

使用注意点

1,await 命令后面的 Promise 对象的运行结果可能是 rejected,所以最好把 await 命令放到 try ...catch 代码块中。

2,多个 await 命令后面的异步操作如果不存在继发关系,最好让它们同时触发。

 // 写法一
    let fooPromise = getFoo();
    let barPromise = getBar();
    let foo = await fooPromise;
    let bar = await barPromise;
​
// 写法二
let [foo, bar] = await Promise.all([getFoo(), getBar()])

​ ​

3,await 命令只能用在 async 函数中,如果用在普通函数中就会报错;forEach() 方法中 使用 async 函数 和 await 命令也会报错,

需要改成 for 循环。

  • 13
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值