ECMAScript 6 学习async函数
Posted saucxs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ECMAScript 6 学习async函数相关的知识,希望对你有一定的参考价值。
1、什么是async函数
2、用法
2.1基本用法
3、语法
3.1返回promise对象
3.2promise状态的变化
3.3await命令
1、什么是async函数
async函数也是异步编程的解决方案。
async函数是对是对generator函数进行了改进。
var readFile = function (fileName) { return new Promise(function (resolve, reject) { fs.readFile(fileName, function(error, data) { if (error) reject(error); resolve(data); }); }); }; var gen = function* () { var f1 = yield readFile(\'/etc/fstab\'); var f2 = yield readFile(\'/etc/shells\'); console.log(f1.toString()); console.log(f2.toString()); };
后边的gen函数,写成async函数
var asyncReadFile = async function () { var f1 = await readFile(\'/etc/fstab\'); var f2 = await readFile(\'/etc/shells\'); console.log(f1.toString()); console.log(f2.toString()); };
async函数就是将generator函数的星号(*)换成async,将yield替换成await。
async函数对generator函数进行改进,体现以下四点。
(1)内置执行器。
generator函数的执行必须依靠执行器,而async函数自带执行器,也就是说,async函数的执行与普通函数一模一样,只要一行。
下面代码调用了asyncReadFile函数,然后就会自动执行,输出最后的结果。这个完全不像generator函数,需要调用next方法,才能得到最终的结果。
var result=asyncReadFile();
(2)更好的语义
async和await,比起星号(*)和yield,语义更清楚。async表示函数中有异步操作,await表示紧跟其后的表达式需要等待结果。
(3)更广的适用性
yield命令后面只能是Thunk函数或者promise对象,而async函数的await命令后面,可以是promise对象和原始类型的值(数值,字符串和布尔值,但这等同于同步操作)
(4)返回值是promise
async函数的返回值是promise对象,执行generator函数返回一个遍历器对象(Iterator对象)方便多了,也就是说,async函数可以看做是多个异步操作,包装成一个promise对象,而await命令是内部then命令的语法糖。
2、用法
2.1基本用法
async函数返回的是一个promise对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
举一个栗子
function timeout(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } async function asyncPrint(value, ms) { await timeout(ms); console.log(value); } asyncPrint(\'hello world\', 5000);
上面代码指定5秒后输出hello world。
async函数多种使用形式
//函数声明 async function foo() {} //函数表达式 const foo = async function () {} //对象的方法 let obj = { async foo() {} } obj.foo().then(...) //箭头函数 const foo = async () => {}; //class方法 class Storage { constructor() { this.cachePromise = caches.open(\'avatars\'); } async getAvatar(name) { const cache = await this.cachePromise; return cache.match(`/avatars/${name}.jpg`); } }
3、语法
async函数的语法规则总体上比较简单,难点是错误处理机制。
3.1返回的promise对象
async函数返回的是promise对象。
async函数内部return语句返回值,会成为then方法回调函数的参数
async function f() { return \'hello world\'; } f().then(v => console.log(v))
上面代码中,函数f内部return 命令返回值,会被then方法回调函数接收到。输出“hello world”。
async函数内部抛出的错误,会导致返回的promise对象变成reject状态。抛出的错误对象会被catch方法回调函数接收到。
3.2promise对象状态变化
async函数返回的promise对象,必须等到内部的所有的await命令后边的promise对象执行完,才会发生状态的改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。
举个栗子
async function getTitle(url) { let response = await fetch(url); let html = await response.text(); return html.match(/<title>([\\s\\S]+)<\\/title>/i)[1]; } getTitle(\'https://tc39.github.io/ecma262/\').then(console.log)
上面代码中,函数getTitle内部有三个操作:抓取网页,取出文本,匹配页面标题。只有三个操作全部完成,才会执行then方法里面console.log。
3.3 await命令
正常情况下,await命令后边是一个promise对象。如果不是,会被转成一个一个立即resolve的promise对象。
async function f() { return await 123; } f().then(v => console.log(v))
上面代码中,await命令的参数是数值123,他被转成promise对象,并立即resolve。
await命令后边的promise对象如果变成reject状态,则reject的参数会被catch方法的回调函数接收到。
举个栗子
async function f() { await Promise.reject(\'出错了\'); } f() .then(v => console.log(v)) .catch(e => console.log(e))
上面代码中,await语句前面没有return,但是reject方法的参数依然传入catch方法的回调函数,这里如果在wawait前面加上return,效果是一样的。
只要一个await语句后面的promise变成了reject,那么整个async函数都会中断执行。
async function f() { await Promise.reject(\'出错了\'); await Promise.resolve(\'hello world\'); // 不会执行 }
上面代码中,第二个await
语句是不会执行的,因为第一个await
语句状态变成了reject
。
以上是关于ECMAScript 6 学习async函数的主要内容,如果未能解决你的问题,请参考以下文章
[ECMAScript] 说说你对async/await的理解?
进阶学习10:ECMAScript——ES2016ES2017新特性