异步请求,我们第一时间想到的应该是promise,但是对于async/await函数也并不陌生。而且async/await函数在运用上可能会更加的方便简单。 那么我们就来剖析一下async/await函数。但是我想在细说async/await之前,还是要先说说generator函数。
generator:generator函数是es6的一种新的数据类型。一个generator看上去像一个函数,但可以返回多次。
function* generator () {
yield '1111'
yield '2222'
yield '3333'
return '44444'
}
let ge = generator()
generator函数和普通函数一样也是通过函数名+()去调用。但是调用完后并不会立即执行,它仅仅是创建了一个generator对象,还没有执行它,如果想要运行generator函数,那就需要通过遍历器对象的next方法。
let a = ge.next() // {value: '1111', done: false}
let b = ge.next() // {value: '2222', done: false}
let c = ge.next() // {value: '3333', done: false}
let d = ge.next() // {value: '4444', done: false}
let e = ge.next() // {value: undefined, done:true}
想要generator函数执行下一步,必须调用遍历起对象的next方法,使得指针移向下一个状态,也就是说,每调用next方法,内部的指针就从函数的头部或者上一次停下来的地方开始执行,知道遇到下一个yield表达式或者是return语句。由此可见,generator函数是分段执行的,yield表达式是暂停执行的标记。而next方法可以回复执行。也就是说上面的可以交出函数的之执行权。
以上这是对generator函数比较简单的介绍,下面我们来看看async/await函数。
其实,async/await函数就是generator函数的语法糖。async/await函数是在es7中推出的一套关于异步的终结解决方案。
function fun () {
return '我是异步方法'
}
async function asyncTest () {
try {
let data = await fun()
console.log(data)
} catch (err) {
console.log(err)
}
}
这是async/await函数的最简单的用法。注:
- async/await出现的异常是无法捕获的,所以这个时候,我们需要借助try...catch来捕获异常;
- async/await函数的声明和普通函数没有什么区别,函数声明式,对象方法,class类方法,和箭头函数等都可以声明async/await函数;
- 任何一个await后面的promise对象变为reject,那么整个async都会被中断;
- async/await函数返回的是一个promise,必须等到内部所有的await后面的promise都执行完成之后,才能发生状态改变,除非遇到return或者是跑出错误,也就是说,只要async函数内部的异步操作执行完成,才会执行then方法指定的回掉函数;
上面我们说到async/await函数其实就是generator的语法糖,那么它实现的原理也就必然会和generator有关。所以,async函数实际上是对generator函数的改进:
- async/await函数自带执行器,所以执行方式和普通函数的执行方式一样,通过函数名+()的方式执行
- async/await比起*/yield函数语义上更加清楚
- */yield函数中,yield命令之后只能是thunk函数或者是Promise对象,而async/await函数的await命令后面,可以是是promise和原始类型的值(数值,字符串和布尔值会自动转化成resolved的promise对象)
- async函数的返回值是一个promise对象,这比generator函数的值是一个Iterator对象方便很多,可以是使用then方法指定下一步的操作
- 进一步来说,async/await函数完全可以看作是多个异步操作,包装成的一个promise对象,而await命令就是内部then命令的语法糖
当然async/await的实现也是基于promise,async函数其实就是把promise做了一个包装,因为await本身返回的也是一个Promise,它只是把await后面的代码放到了await返回的Promise的.then后面,以此来实现的。看下面的俩段代码,他们是等价的。
getConstant() {
return 1
}
async getAsyncConstant() {
return 1
}
async getPromise() {
return new Promise((resolved, rejected)=> {
resolved(1)
});
}
async test() {
let a = 2
let c = 1
await getConstant();
let d = 3
await getPromise();
let d = 4
await getAsyncConstant();
return 2
}
function getConstant() {
return 1;
}
function getAsyncConstant() {
return Promise.resolve().then(function () {
return 1;
});
}
function getPromise() {
return Promise.resolve().then(function () {
return new Promise((resolved, rejected) => {
resolved(1);
});
});
}
test() {
return Promise.resolve().then(function () {
let a = 2;
let c = 1;
return getConstant();
}).then(function () {
let d = 3;
return getPromise();
}).then(function () {
let d = 4;
return getAsyncConstant();
}).then(function () {
return 2;
});
}
就是这样。。。。