js异步(二)async / await 理解总结


语法

async function name([param[, param[, ... param]]]) { statements }

 async 函数会返回一个 Promise 对象,如果在函数中 return 一个直接量,async 会把它通过 Promise.resolve() 封装成 Promise 对象;当 async 函数抛出异常时,Promise 的 reject 方法也会传递这个异常值。

async function hello() {
    return 'hello, world';
}
console.log(hello()); // Promise { 'hello, world' }
async function error() {
    throw 'error';
}
console.log(error()); // Promise { <rejected> 'error' }
[return_value] = await expression;

 await 会暂停当前 async function 的执行,等待 Promise 处理完成,若成功,其回调的 resolve 函数的参数作为 await 表达式的值,然后继续执行 async function;否则把 Promise 的异常原因抛出;若 await 后的表达式的值不是Promise,则返回该值本身。

function timeout(n) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(n + 200); 
        }, n)
    })
}
async function foo() {
    let x = await timeout(500);
    console.log(x); // 700
}
foo();

注:await 关键字只有在 async function 中有效,如果在这之外使用 await,只会得到一个语法错误。

执行时间

 async 函数调用不会造成阻塞,但是执行到 await 时,await 会阻塞后面代码的运行,等待异步操作结束,获得返回值

function asyFun() {
    return new Promise((resolve) => {
        resolve('resolve');
    });
}
async function foo() {
    console.log('async Function starts')
    let result = await asyFun();
    console.log(result);
}
foo();
console.log('after async Function');
// async Function starts
// after async Function
// resolve

 注:因为 await 会阻塞其后代码运行,所以多个 await 命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。

优势

处理 then 链

async / await 的目的是简化使用多个 Promise 时的同步行为,并对一组 Promise 执行某些操作。

对于一些需要异步返回值作为参数的操作,使用 async / await 就会很方便

function timeout(n) {
    return new Promise((resolve, reject) => {
        // 一些异步操作
        setTimeout(() => {
           resolve(n + 200); 
        }, n)
    })
}

const time1 = 500;
function takeALongTime() {
    timeout(time1)
    .then(time2 => {
        console.log(time1, time2);
        return timeout(time2).then( time3 => [time1, time2, time3]);
    })
    .then(times => {
        const [time1, time2, time3] = times;
        console.log(time1, time2, time3);
        return timeout(time3);
    })
    .then(result => {
        console.log('result', result);
    })
}
takeALongTime();

如果使用 Promise,在传递参数时就会很麻烦,需要不断地返回并在下一个.then中接收,如果使用 async / await 的话,代码就会变得相对直观,可以像写同步代码一样写,将返回值储存在变量中

const time1 = 500;
async function takeALongTime() {
    console.log('start async');
    let time2 = await timeout(500);
    console.log(time1, time2);
    let time3 = await timeout(time2);
    console.log(time1, time2, time3)
    let result = await timeout(time3);
    console.log('result', result);
}
takeALongTime();

错误处理

最好将 await 放在 try ... catch 中防止出错

function asyFun() {
    return new Promise((resolve) => {
        resolve('resolve');
    });
}

const makeRequest = async () => {
    try{
        await asyFun();
        await asyFun();
        await asyFun();
        throw new Error("error");
    } catch(error) {
        console.log(error);
    }
};
makeRequest();
//Error: error
//    at makeRequest (D:\StudyFiles\asynchronous\promiseTest.js:71:15)
//    ...

因为async 函数可以保留运行堆栈,错误可以定位到 makeRequest() 函数

但是如果用 .then() 的话

const makeRequest = () => {
    return asyFun()
        .then(() => asyFun())
        .then(() => asyFun())
        .then(() => asyFun())
        .then(() => {
            throw new Error("error");
        });
};

makeRequest().catch(err => {
    console.log(err);
});
// Error: error
//    at asyFun.then.then.then.then (D:\StudyFiles\asynchronous\promiseTest.js:84:19)
//    ...

因为异步执行,抛出错误时 makeRequest 函数已经执行完毕,错误只会定位在 asyFun 中。

 

参考:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值