【问题标题】:Something like async_hooks for the browser?像浏览器的 async_hooks 之类的东西?
【发布时间】:2022-03-06 21:18:48
【问题描述】:

我正在尝试调试在浏览器上下文中运行的一些(第三方)代码,并且我想跟踪所有下游异步函数调用,这与 nodejs 提供的 async_hooks 几乎完全相同。本质上,类似于https://github.com/mafintosh/why-is-node-running,但在浏览器中。我会满足于“接近的东西”,或者如果我必须要修补全局变量......

任何人都知道远程关闭的东西吗?这个 (https://stackoverflow.com/a/49245432/1256988) 看起来很有希望,但它似乎不适用于我的子呼叫?!

我应该指出,我在这里的实际用途实际上只是保持异步函数调用的计数,以便在我的测试结束时,我知道我是否“泄露”了异步调用。

我还应该指出,这 (https://github.com/AndreasMadsen/async-hook/issues/15) 似乎表明我在浏览器中可能不走运(尽管我只能得到大约正确的结果)。

【问题讨论】:

  • 如果没有原生支持,我认为无法直接替换 async_hooks。只是方式需要修补太多的 Web API 才能实现这一点,而且内存泄漏很容易通过非本地补丁意外引入,因为承诺没有当 t 已解决的未绑定到开放资源并且无法履行或拒绝它们时,允许 GC'd。
  • 好吧,我想这会是这样。我会让这个打开一段时间,但你在这里的评论可能就是答案:(

标签: javascript debugging async-await


【解决方案1】:

Zone.js 在这方面做得很好。它是 Angular 在内部用于跨异步调用跟踪状态的,但它确实作为单独的 API 存在。它通过修补整个浏览器 API 负载(例如 setTimeout、事件订阅等)来工作

下面是一段 HTML 示例,展示了它的使用情况。它运行几个区域(基本上是线程上下文)并在每个区域中进行异步工作。您可以看到当前区域在异步工作流程中神奇地被传递。

<html>
  <script src="https://unpkg.com/zone.js@0.11.5/bundles/zone.umd.js"></script>
  <script>
    const rootZone = Zone.current;

    // Create two zones (thread contexts, basically)
    const zone1 = rootZone.fork({
      name: 'zone1',
      properties: { pizzaInfo: { topping: 'pepperoni' } },
    });
    const zone2 = rootZone.fork({
      name: 'zone2',
      properties: { pizzaInfo: { topping: 'pineapple' } },
    });

    // A function which will trigger some asynchronous work
    // Doesn't know anything about zones, but magically the
    // work will run in whatever zone launched it.
    function someWork() {
      setTimeout(someAsyncWork, 1000);
    }

    // Some asynchronous work
    function someAsyncWork() {
      const initialZone = Zone.current;
      const pizzaInfo = initialZone.get('pizzaInfo');

      console.log(`someAsyncWork: in zone ${initialZone.name}`);
      console.log(`someAsyncWork: best pizza topping for this zone is ${pizzaInfo.topping}`);

      // Have some async fun with promises and timers
      delay(500).then(yetMoreWork);
    }

    function yetMoreWork() {
      const zone = Zone.current;
      console.log(`yetMoreWork: in zone ${zone.name}`);
    }

    function delay(millis) {
      return new Promise((resolve) => setTimeout(resolve, millis));
    }

    zone1.run(someWork);
    zone2.run(someWork);
  </script>
</html>

(这是该代码的 JSFiddle:https://jsfiddle.net/rbkxd512/

Zone.js 有很多需要在浏览器中修补的地方,所以它被分成模块,你可以根据你是否关心多媒体 API、网络 API 等来选择这些模块。

【讨论】:

    猜你喜欢
    • 2017-01-30
    • 2012-06-04
    • 1970-01-01
    • 2013-12-20
    • 2010-10-16
    • 2011-05-25
    • 2012-12-15
    • 2012-10-19
    相关资源
    最近更新 更多