• 前端JavaScript中异步的终极解决方案:async/await


     

    🎬 江城开朗的豌豆个人主页

     🔥 个人专栏 :《 VUE 》 《 javaScript 》

    ⛺️ 生活的理想,就是为了理想的生活 !

    在这里插入图片描述

    目录

    1. 背景

    2. 使用方法

    3. 实现原理


    1. 背景

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

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

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

    2. 使用方法

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

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

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

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

    1. async function getData() {
    2. try {
    3. const response = await fetch('https://api.example.com/data');
    4. const data = await response.json();
    5. return data;
    6. } catch (error) {
    7. console.error('Error:', error);
    8. throw error;
    9. }
    10. }
    11. getData()
    12. .then(data => console.log('Data:', data))
    13. .catch(error => console.error('Error:', error));

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

    3. 实现原理

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

    1. function promiseFn() {
    2. return new Promise((resolve) => {
    3. setTimeout(() => {
    4. resolve('promise resolved');
    5. }, 2000);
    6. });
    7. }
    8. function* genFn() {
    9. let result = yield promiseFn();
    10. console.log(result);
    11. }
    12. function asyncToGenerator(generator) {
    13. let gen = generator();
    14. return new Promise((resolve, reject) => {
    15. function step(key, arg) {
    16. let result;
    17. try {
    18. result = gen[key](arg);
    19. } catch (error) {
    20. return reject(error);
    21. }
    22. const { value, done } = result;
    23. if (done) {
    24. return resolve(value);
    25. } else {
    26. return Promise.resolve(value).then(val => {
    27. step('next', val);
    28. }, err => {
    29. step('throw', err);
    30. });
    31. }
    32. }
    33. step('next');
    34. });
    35. }
    36. asyncToGenerator(genFn);

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

  • 相关阅读:
    mongoose实现httpserver,client
    MindSpore数据集加载-GeneratorDataset数据处理报错:The pointer[cnode] is null
    监控web项目都访问了那些网址
    6.DesignForPlacement\2.PdfSchematicInteractive
    2022数据结构习题(知产)
    STC89C52定时器/中断快速上手示例讲解
    如何使用Python和Plotly绘制3D图形
    Java数据结构—队列
    无法在 DLL“SQLite.Interop.dll”中找到名为”sIb4c632894b76cc1d“
    23062C++&QTday3
  • 原文地址:https://blog.csdn.net/qq_48652579/article/details/132904076