详解 ES8 中的异步函数 Async/Await 实现原理及优化方法

异步编程是现代前端开发中不可避免的技术要素,它的出现是为了解决 JavaScript 单线程的限制,可以更好的处理好页面渲染以及用户交互体验等问题。在 ES8 中,异步编程有了更为便捷的实现方式:Async/Await。

什么是 Async/Await

Async/Await 是 ES8 中新增的异步编程方式,它是对 Promise 的一层封装。通过 Async 函数和 Await 表达式,可以更加轻松地实现异步编程。所谓 “Async” 即异步的意思,“Await” 即等待的意思。

Async/Await 的使用方法

  • 定义 Async 方法

Async 方法需要用 async 关键字来修饰,其可以不加参数,也可以加上请求所需参数。

  • Await 表达式

Await 表达式是 Async 函数中的语句,在这里可以暂停 Async 方法的执行,直到 Await 表达式的 Promise 对象是 resolved。如果 Promise 返回的 status 是 rejected,则会抛出异常。可以将 Await 表达式赋值给一个变量,以便后续处理。

下面是一个使用 Async/Await 的示例代码:

async function foo() {
    try {
        const result = await promise;
        console.log(result);
    } catch (error) {
        console.error(error);
    }
}

foo();

Async/Await 的实现原理

Async/Await 的实现原理基于 Generator,也就是说,Async 函数是 Generator 函数的语法糖。

  • Async 函数通过返回一个 Promise 对象来实现异步操作

在 Async 函数的内部实现,它通过 Generator 函数来实现异步操作,返回值是一个 Promise 对象。

下面是一个 Async 函数的示例代码:

async function bar() {
    const result = await fakeRequest('/data.json');
    return result;
}

bar().then(result => console.log(result));
  • 使用 Generator 函数来实现异步操作

当我们在 Async 函数使用 await 表达式的时候,就相当于 Yield 表达式的效果,表明等待异步操作完成。当其完成之后,再将结果作为结果对象的属性值,再调用 Generator 函数的 next 方法。

异步操作的状态是 Promise 对象实现的,Generator 函数有两个重要性质:

下面是一个基于 Generator 的异步编程示例代码:

function* foo() {
    const result = yield request('/data.json');
    console.log(result);
}

function request(url) {
    return fetch(url).then(response => response.json());
}

const iterator = foo();
const promise = iterator.next().value;

promise.then(result => iterator.next(result));

Async/Await 的优化方法

虽然 Async/Await 语法更加简洁,但是在使用过程中,我们依然需要注意一些优化方法,以提高代码的性能和可维护性。

1. 处理错误的方式

在 Async 函数中使用 try-catch 来处理错误,可以更加直观地了解哪个异步函数返回了错误。

async function foo() {
    try {
        const result = await promise;
        console.log(result);
    } catch (error) {
        console.error('Error:', error);
    }
}

foo();

2. 并发请求(Promise.all)

如果有多个异步请求需要被处理,可以通过 Promise.all 对它们进行处理。这个方法接受一个包含多个 Promise 实例的数组,当所有的 Promise 都完成之后,将返回所有 Promise 对象的值的数组,以便后续处理。

下面是一个并发请求的示例代码:

async function foo() {
    try {
        const [result1, result2] = await Promise.all([
            promise1,
            promise2,
        ]);
        console.log(result1, result2);
    } catch (error) {
        console.error('Error:', error);
    }
}

foo();

3. Async 函数串行执行

在异步编程中,有时候我们需要一些异步操作按顺序执行,可以使用在每个异步操作之间添加 await 表达式的方式,以便实现串行执行的效果。

下面是一个异步函数串行执行的示例代码:

async function foo() {
    try {
        const result1 = await request('/data.json');
        console.log(result1);
        const result2 = await request('/data2.json');
        console.log(result2);
    } catch (error) {
        console.error('Error:', error);
    }
}

foo();

总结

Async/Await 是一种相对传统的 Promise 的简洁写法,能够让我们更加方便的实现异步编程,同时需要注意优化性能和代码可维护性。熟练掌握它的语法以及实现原理,可以更好地编写高质量的异步代码。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a76633add4f0e0ff07383b


纠错反馈