JavaScript 理解异步函数、async/await关键字

1. Promise

异步函数,即async / await,是基于Promise的应用,可以让我们以同步的方式写异步的代码。

如下代码,一个使用Promise的简单例子,Promise对象中的函数参数中,写了一个定时器setTimeout。定时器的第三个参数为10,表示定时器结束后,10将作为参数,传递给定时器的回调函数resolve。这就意味着,定时器结束后,这个Promise对象会解决为数值10

const p = new Promise((resolve, reject) => setTimeout(resolve, 1000, 10));

但是,如果访问到这个数值10,需要调用then()方法:

p.then(x => console.log(x)); // 10

这非常不方便,虽然解决了回调地域问题,但是后续代码必须要放在then()方法里面。

在 ES8 中,JavaScript 支持了async / await关键字,可以用同步的方式,写异步代码。

2. async 关键字

async关键字用来声明异步函数,可以在函数声明、函数表达式、箭头函数、方法前声明使用:

// 函数声明
async function fun1() {}

// 函数表达式
const fun2 = async function () {};

// 箭头函数
const fun3 = async () => {};

// 方法
const obj = {
    async fun4() {},
};

使用async关键字可以让函数具有异步的特征,但代码还是同步求值的:

async function fun() {
    console.log(1);
}

fun();
console.log(2);
// 1
// 2

如上代码,fun函数被声明成异步函数,但总体代码仍然是同步执行的,因为先打印出了1,再打印2

另外,被async声明的函数如果使用return返回了值(若没有return,则返回undefined),那么返回的值会被Promise.resolve()包装成一个Promise对象。所以,异步函数始终会返回Promise对象。

如下代码,调用fun函数,fun函数内部首先打印出1,接着返回Promise对象,然后打印出2,最后打印出Promise对象解决的值3

async function fun() {
    console.log(1);
    return 3;
}

fun().then(console.log);

console.log(2);
// 1
// 2
// 3

异步函数内部直接返回一个Promise对象也能达到同样效果,如下代码等价于上面的代码:

async function fun() {
    console.log(1);
    return Promise.resolve(3);
}

fun().then(console.log);

console.log(2);
// 1
// 2
// 3

但是,若Promise被拒绝,那么将不会被异步函数捕获:

async function fun() {
    console.log(1);
    Promise.reject(3);
}

fun().then(console.log);

console.log(2);
// 1
// 2
// 报错:Unhandled promise rejection

3. await 关键字

使用await关键字可以暂停异步函数代码的执行,等待Promise解决。

本文首个例子:

const p = new Promise((resolve, reject) => setTimeout(resolve, 1000, 10));
p.then(x => console.log(x)); // 10

可以使用asyncawait关键字改写为:

async function fun() {
    const p = new Promise((resolve, reject) => setTimeout(resolve, 1000, 10));
    console.log(await p);
}

fun(); // 10

await关键字会暂停执行异步函数后面的代码,让出 JavaScript 运行时的执行线程

但是,await必须和async一起使用,也就是说,await只能写在被async声明过的异步函数中。若await写在同步函数中,将会报错:

function fun() {
    let a = await 1; // SyntaxError: await is only valid in async function
    console.log(a);
}

fun();

参考:

《JavaScript高级程序设计(第4版)》


欢迎在我的博客上访问:
https://lzxjack.top/

你可能感兴趣的:(前端面试-JavaScript,javascript,前端,es6)