带你读《现代Javascript高级教程》二十九、异步的终极解决方案:async/await

简介: 带你读《现代Javascript高级教程》二十九、异步的终极解决方案:async/await

二十九、异步的终极解决方案:async/await

1. 背景

在深入讨论 async/await 之前,我们需要了解一下 JavaScript 的单线程和非阻塞的特性。JavaScript 是单线程的,也就是说在任何给定的时间点,只能执行一个操作。然而,对于需要大量时间的操作(例如从服务器获取数据),如果没有适当的管理机制,这种单线程特性可能会导致应用程序的阻塞。为了解决这个问题,JavaScript 引入了回调函数和后来的 Promise,用来管理这些异步操作。

然而,回调函数和 Promise 还是存在一些问题。回调函数很容易导致 "回调地狱",因为每个异步操作都需要一个回调函数,如果有很多这样的操作,代码就会变得非常混乱。Promise 解决了这个问题,让异步代码更加直观,但是,Promise 的链式调用有时候还是显得不够直观。

为了结合Promise和生成器的优势,Async/awaitECMAScript 2017ES8)中被引入。它通过async函数和await表达式提供了一种更加直观和简洁的方式来编写异步代码,消除了回调函数和手动管理Promise的需要。

2. 使用方法

Async/await的使用方法非常简单明了,主要涉及两个关键字:asyncawait

async关键字:用于声明一个async函数,它返回一个Promise对象。在async函数内部,我们可以使用await关键字来暂停函数的执行,等待一个异步操作的完成,并获得其结果。在这个过程中,async函数会暂时释放线程的控制权,使其他代码可以继续执行。

await关键字:用于暂停async函数的执行,等待一个Promise对象的完成,并返回其解析的值。它只能在async函数内部使用。当使用await表达式时,代码的执行会暂停,直到Promise对象被解析或拒绝。

下面是一个示例,展示了Async/await的使用方法:

async function getData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error:', error);
    throw error;
  }}
getData()
  .then(data => console.log('Data:', data))
  .catch(error => console.error('Error:', error));

 

在上面的示例中,getData函数是一个async函数,它等待fetch函数返回的Promise对象,并使用await关键字获取响应的数据。最后,我们使用.then方法处理返回的数据,或使用.catch方法处理可能发生的错误。

3. 实现原理

Async/Await 的实现原理其实就是 Generator + Promise。我们知道 Generator 可以在 yield 关键字处暂停和恢复执行,Promise 可以处理异步操作,两者结合在一起,就可以实现一个类似于 async/await 的功能。

function promiseFn() {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve('promise resolved');
        }, 2000);
    });}function* genFn() {
    let result = yield promiseFn();
    console.log(result);}function asyncToGenerator(generator) {
    let gen = generator();
    return new Promise((resolve, reject) => {
        function step(key, arg) {
            let result;
            try {
                result = gen[key](arg);
            } catch (error) {
                return reject(error);
            }
            const { value, done } = result;
            if (done) {
                return resolve(value);
            } else {
                return Promise.resolve(value).then(val => {
                    step('next', val);
                }, err => {
                    step('throw', err);
                });
            }
        }
        step('next');
    });}asyncToGenerator(genFn);

 

在上述代码中,我们首先创建了一个 promiseFn 函数,该函数返回一个在 2 秒后解析的 Promise。然后,我们创建了一个 Generator 函数 genFn,在该函数内部,我们使用 yield 关键字暂停执行并等待 promiseFn 的结果。最后,我们创建了一个 asyncToGenerator 函数,该函数接受一个 Generator 函数作为参数,并返回一个新的 Promise,这个 Promise 的解析值就是 Generator 函数的返回值。

4. 参考资料

  • MDN Web Docs: Async functionsopen in new window
  • MDN Web Docs: await

 

相关文章
|
3天前
|
前端开发 JavaScript API
Howler.js:音频处理的轻量级解决方案
Howler.js:音频处理的轻量级解决方案
|
3天前
|
前端开发 JavaScript UED
深入理解 JavaScript 同步和异步,让网页灵动起来!
深入理解 JavaScript 同步和异步,让网页灵动起来!
|
5天前
|
JavaScript 前端开发 网络安全
【网络安全 | 信息收集】JS文件信息收集工具LinkFinder安装使用教程
【网络安全 | 信息收集】JS文件信息收集工具LinkFinder安装使用教程
16 4
|
2天前
|
前端开发 JavaScript
JavaScript新科技:PostCSS的安装和使用,2024年最新2024网易Web前端高级面试题总结
JavaScript新科技:PostCSS的安装和使用,2024年最新2024网易Web前端高级面试题总结
|
2天前
|
JavaScript 前端开发
web前端JS高阶面试题(1),高级开发工程师面试
web前端JS高阶面试题(1),高级开发工程师面试
|
2天前
|
前端开发 JavaScript UED
前端 js 经典:async 和 await
前端 js 经典:async 和 await
10 2
|
3天前
|
JavaScript 前端开发
深入理解Vue.js中的nextTick:实现异步更新的奥秘
深入理解Vue.js中的nextTick:实现异步更新的奥秘
|
3天前
|
移动开发 JavaScript 前端开发
Web Worker:JavaScript的后台任务解决方案
Web Worker:JavaScript的后台任务解决方案
|
5天前
|
前端开发 JavaScript UED
由于JavaScript是单线程的,因此在处理大量异步操作时,需要确保不会阻塞UI线程
【5月更文挑战第13天】JavaScript中的Promise和async/await常用于处理游戏开发中的异步操作,如加载资源、网络请求和动画帧更新。Promise表示异步操作的结果,通过.then()和.catch()处理回调。async/await作为Promise的语法糖,使异步代码更简洁,类似同步代码。在游戏循环中,使用async/await可清晰管理资源加载和更新,但需注意避免阻塞UI线程,并妥善处理加载顺序、错误和资源管理,以保证游戏性能和稳定性。
12 3