ES7之async,await

ES7之async,await


一、基本用法

async,await函数是ES7中引入的语法。与Generator,Promise有很大的关系。

async

使用async修饰的函数,会返回一个Promise对象。

async function func() {
    return 'a';
}

let res = func();
console.log(res);  //Promise { 'a' }

res.then((value)=>{
    console.log(value);  //a
})

await
async函数中可能包含await表达式,执行到到await表达式时,就会暂停当前函数的执行,直到触发的异步操作执行完成。
await函数只能在async函数中使用,否则会报语法错误。
await表达式的值根据await后面的表达式的值有关:

  • 如果是Promise对象: async函数停止执行,等待Promise对象Resolve,最后表达式的值即为Resolve的值
  • 如果不是Promise对象:最后表达式的值为await最后表达式的值。
function testAwait (x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}
 
async function AsyncFunc() {
  let x = await testAwait ("hello world");
  console.log(x); 
}
AsyncFunc();

二.原理

function sumAsync (a, b) {
    return new Promise((resolve, reject)=>{
        setTimeout(()=>{
            resolve((a+b));
        },1000);
    });
}

function * g () {
    let sum = yield sumAsync(1,2);
    return sum;
}

let it = g();
let promise = it.next();
promise.value.then(value => {
    console.log(value);
})
//相比于
async function g() {
    let sum = await sumAsync(1,2);
    return sum;
}

上面的代码中,可以看到async函数于generator函数十分相似,其实async就是generator函数,只不过多了一个执行器。

执行器:在上面的代码中 generator函数的执行需要两个步骤

let it = g();
let promise = it.next();
promise.value.then(value => {
    console.log(value);
})

可以写一个执行器excute()来封装一下上面的代码。

//模拟一个异步请求
function getNum (num) {
    return new Promise((resolve, reject) => {
        setTimeout(()=>{
            resolve(num);
        },1000)
    });
}
//执行器
function excute (generator,...args) {
    let iter = generator.apply(this,args);
    let n = iter.next();
    if(n.done) {
        return new Promise((resolve => resolve(n.value)));
    }else{
        return new Promise(((resolve) => {
            n.value.then((ret) => {
                _r(iter,ret,resolve)
            })
        }));
    }
}
function _r (iter,ret,resolve) {
    let n = iter.next(ret);
    if(n.done) {
        resolve(n.value);
    }else {
        n.value.then(ret=>{
            _r(iter,ret,resolve);
        });
    }

}
//Generator函数
function * generator () {
    let r1 = yield getNum(1);
    console.log(r1);
    let r2 = yield getNum(2);
    console.log(r2);
    console.log('end');
}
excute(generator).then(value => {
    console.log(value);
})
//输出
//1
//2
//end
//undefined

总之,async函数就是内置了执行器的generator函数,当执行async函数时,js引擎会调用执行器。

相关面试题


async function async1(){
    console.log('async1 start')
    await async2()
    console.log('async1 end')
}
async function async2(){
    console.log('async2')
}
console.log('script start')
setTimeout(function(){
    console.log('setTimeout')
},0)
async1();
new Promise(function(resolve){
    console.log('promise1')
    resolve();
}).then(function(){
    console.log('promise2')
})
console.log('script end')
  • 首先,打印’script start’,执行到setTimeout,把setTimeout的内容放到宏任务中.
  • 接着执行到async1()函数,首先打印’async1 start’,执行到await表达式,发现async2() 是一个async修饰的函数,所以先执行async2()函数里的代码,返回的Promise会被放到回调队列中等待,然后await会让出进程,跳出async1()函数,执行后面的代码。
  • 之后执行Promise中的代码,打印’promise1’,然后把.then放到回调队列中,接着打印script end
  • 同步的事件都循环执行完了,执行回调队列的内容,打印promise2。然后接着执行async1()函数后面的代码,打印’async1 end’,
  • 执行下一个宏任务,打印setTimeout.

Async,Await 是否可以取代Promise

const timeoutFn = function(value,timeout){
    return new Promise(function(resolve){
        return setTimeout(()=>{resolve(value)},timeout);
    });
}
async function getABC() {
    let A = await timeoutFn(2,2000); // 2 second to finish
    let B = await timeoutFn(2,2000); // 4 second to finish
    let C = await timeoutFn(3,3000); // 3 second to finish
    return A*B*C;
}
getABC()
    .then((res)=>{
        console.log(res)
        //12
    });

对于上面的情况,三个变量不相互依赖,每一个表达式都会等待上一个返回结果,所以会在7s后返回结果。

如果使用Promise.all(),允许我们同时发送所有请求,异步触发,会在3返回结果12

const timeoutFn = function(value,timeout){
    return new Promise(function(resolve){
        return setTimeout(()=>{resolve(value)},timeout);
    });
}
async function getABC() {
    let res = await Promise.all([timeoutFn(2,2000),timeoutFn(2,2000),timeoutFn(3,3000)]);
    return new Promise(resolve => resolve(res.reduce((total,value)=>total+=value)))
}
getABC()
    .then((res)=>{
        console.log(res)
        //12
    });

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值