当前位置: 首页 > article >正文

25-深入理解 JavaScript 异步生成器的实现

笔记+分享

在现代 JavaScript 中,async/await 已经成为处理异步任务的常见选择,但在某些不支持原生 async/await 的环境中,我们可能需要通过生成器(Generators)来实现异步逻辑。本文将详细剖析一个 JavaScript 异步生成器控制器的实现过程,帮助您深入理解其工作原理。

背景介绍:生成器和异步生成器

生成器是 JavaScript 中的一种函数类型,调用生成器函数时返回一个迭代器对象,可以通过 next 方法一步步执行,并根据需要暂停和恢复执行。异步生成器类似,但它可以在暂停的间隙等待异步操作完成,再继续执行。

代码结构分析

以下是代码的结构。我们将逐步解释各个函数的作用,以帮助理解其整体设计。

1. 类型检测函数 t

function t(r) {
  return (
    (t = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator
      ? function (t) { return typeof t; }
      : function (t) {
          return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t;
      }
    ),
    t(r)
  );
}
解释

t 是一个类型检测函数,用于判断传入变量 r 的类型,特别是检查是否为 Symbol 类型。通过闭包保存类型检测方法,它在后续调用时直接调用已缓存的检测逻辑,避免重复判断。

2. 异步生成器控制器 r

function r() {
  "use strict";
  r = function () { return n; };
  var e, n = {}, o = Object.prototype, i = o.hasOwnProperty, a = "function" == typeof Symbol ? Symbol : {}, c = a.iterator || "@@iterator", u = a.asyncIterator || "@@asyncIterator", l = a.toStringTag || "@@toStringTag";

  function f(t, r, e) { // 定义属性方法
    return Object.defineProperty(t, r, { value: e, enumerable: !0, configurable: !0, writable: !0 }), t[r];
  }

  function s(t, r, e, n) { // 创建生成器实例
    var o = r && r.prototype instanceof v ? r : v,
        i = Object.create(o.prototype),
        a = new _(n || []);
    return (i._invoke = function (t, r, e) {
      var n = "suspendedStart";
      return function (o, i) {
        if ("executing" === n) throw new Error("Generator is already running");
        if ("completed" === n) {
          if ("throw" === o) throw i;
          return { value: void 0, done: !0 };
        }
        for (e.method = o, e.arg = i; ;) {
          var a = e.delegate;
          if (a) {
            var c = m(a, e);
            if (c) {
              if (c === d) continue;
              return c;
            }
          }
          if ("next" === e.method) e.sent = e._sent = e.arg;
          else if ("throw" === e.method) {
            if ("suspendedStart" === n) throw ((n = "completed"), e.arg);
            e.dispatchException(e.arg);
          } else "return" === e.method && e.abrupt("return", e.arg);
          n = "executing";
          var u = p(t, r, e);
          if ("normal" === u.type) {
            if (((n = e.done ? "completed" : "suspendedYield"), u.arg === d)) continue;
            return { value: u.arg, done: e.done };
          }
          "throw" === u.type && ((n = "completed"), (e.method = "throw"), (e.arg = u.arg));
        }
      };
    })(t, e, a), i;
  }

  function p(t, r, e) { // 捕获执行异常
    try {
      return { type: "normal", arg: t.call(r, e) };
    } catch (t) {
      return { type: "throw", arg: t };
    }
  }

  n.wrap = s;
  return n;
}
解释

r 是核心的异步生成器控制器。它包含多种方法来处理生成器的各个状态,确保生成器能够正确地执行异步逻辑。

  • f 函数:简化 Object.defineProperty,用于定义对象属性。
  • s 函数:生成器控制器的创建函数,通过 _invoke 方法控制生成器的执行,确保其按顺序执行。
  • p 函数:使用 try-catch 捕获执行时的错误并返回,保证异常能在生成器的异步处理中正确处理。

3. 定义属性的帮助函数 h

function h(t, r, e) {
  Object.defineProperty(t, r, { value: e, enumerable: !0, configurable: !0, writable: !0 });
}
解释

h 是简化的 Object.defineProperty,为对象 t 定义属性 r,其值为 e。此函数使代码在定义属性时更加简洁和通用。


4. 创建生成器实例的核心函数 s

function s(t, r, e, n) {
  var o = r && r.prototype instanceof v ? r : v,
      i = Object.create(o.prototype),
      a = new _(n || []);
  return (i._invoke = function (t, r, e) {
    var n = "suspendedStart";
    return function (o, i) {
      if ("executing" === n) throw new Error("Generator is already running");
      if ("completed" === n) {
        if ("throw" === o) throw i;
        return { value: void 0, done: !0 };
      }
      for (e.method = o, e.arg = i; ;) {
        var a = e.delegate;
        if (a) {
          var c = m(a, e);
          if (c) {
            if (c === d) continue;
            return c;
          }
        }
        if ("next" === e.method) e.sent = e._sent = e.arg;
        else if ("throw" === e.method) {
          if ("suspendedStart" === n) throw ((n = "completed"), e.arg);
          e.dispatchException(e.arg);
        } else "return" === e.method && e.abrupt("return", e.arg);
        n = "executing";
        var u = p(t, r, e);
        if ("normal" === u.type) {
          if (((n = e.done ? "completed" : "suspendedYield"), u.arg === d)) continue;
          return { value: u.arg, done: e.done };
        }
        "throw" === u.type && ((n = "completed"), (e.method = "throw"), (e.arg = u.arg));
      }
    };
  })(t, e, a), i;
}
解释
  • 生成器实例i 是生成器实例,通过闭包保存并控制生成器的执行顺序。
  • _invoke 方法:控制生成器的执行状态,如 suspendedStartexecuting 和 completed,确保生成器不会被重复执行。

5. 执行异步生成器的核心部分

function () {
  var t = this, r = arguments;
  return new Promise(function (o, i) {
    var a = n.apply(t, r);
    function c(t) {
      e(a, o, i, c, u, "next", t);
    }
    function u(t) {
      e(a, o, i, c, u, "throw", t);
    }
    c(void 0);
  });
})();
解释

最后,这段匿名函数通过 Promise 包装生成器,使其具有异步行为。c 和 u 方法分别对应生成器的 next 和 throw 操作,确保生成器的 next 方法能继续执行。


总结

本文解析了一个 JavaScript 异步生成器控制器的实现。通过这种控制器,您可以在不支持 async/await 的环境中,管理基于生成器的异步操作。这一实现方式不仅提高了代码兼容性,还帮助我们更深入地理解了异步生成器的内部工作机制。


http://www.kler.cn/a/399112.html

相关文章:

  • 2020年计挑赛往届真题(C++)
  • ARM 汇编指令
  • React中组件通信的几种方式
  • uniapp自动注册机制:easycom
  • 【Mysql】Mysql的多表查询---多表联合查询(上)
  • Android Mobile Network Settings | APN 菜单加载异常
  • 基于Java的旅游类小程序开发与优化
  • Qt桌面应用开发 第四天(对话框 界面布局)
  • 【项目开发】理解SSL延迟:为何HTTPS比HTTP慢?
  • MoneyPrinterTurbo - AI自动生成高清短视频
  • 学习大数据DAY62 指标计算
  • mybatisPlus打印sql配置
  • Java面试之多线程并发篇(3)
  • 【51单片机】LCD1602液晶显示屏
  • Spring Boot 应用程序中集成 Redis 并实现存储读取字符串或者复杂对象
  • 【MySQL】MySQL的笛卡尔积现象是什么?简单说说
  • Django数据写入MySQL数据库
  • 蓝牙 HFP 协议详解及 Android 实现
  • 用 Python 从零开始创建神经网络(八):梯度、偏导数和链式法则
  • Elasticsearch基本概念及使用
  • css:修改盒子样式
  • vue3 查看word pdf excel文件
  • 【论文阅读】(Security) Assertions by Large Language Models
  • # JAVA中的Stream学习
  • STM32设计防丢防摔智能行李箱
  • 计算机毕业设计 | springboot+vue大学城水电管理系统 校园学校物业水电管理(附源码+文档)