使用 rxjs 时如何获取错误的堆栈跟踪?

Posted

技术标签:

【中文标题】使用 rxjs 时如何获取错误的堆栈跟踪?【英文标题】:How to get the stacktrace of an error when using rxjs? 【发布时间】:2017-02-25 03:59:39 【问题描述】:

我正在使用 angular-cli 构建一个小型 angular2 Web 应用程序,并且正在使用 chrome dev-tools 进行调试。

如果我每次都需要猜测错误的来源以及该错误的堆栈跟踪是什么,那么显然我做错了。

以这个错误为例:

error_handler.js:45EXCEPTION: Cannot read property 'provider' of nullErrorHandler.handleError @ error_handler.js:45
error_handler.js:50ORIGINAL STACKTRACE:ErrorHandler.handleError @ error_handler.js:50
error_handler.js:51TypeError: Cannot read property 'provider' of null
    at MapSubscriber.project (auth.effects.ts:80)
    at MapSubscriber._next (map.js:77)
    at MapSubscriber.Subscriber.next (Subscriber.js:89)
    at DistinctUntilChangedSubscriber._next (distinctUntilChanged.js:72)
    at DistinctUntilChangedSubscriber.Subscriber.next (Subscriber.js:89)
    at MapSubscriber._next (map.js:83)
    at MapSubscriber.Subscriber.next (Subscriber.js:89)
    at MapSubscriber._next (map.js:83)
    at MapSubscriber.Subscriber.next (Subscriber.js:89)
    at RefCountSubscriber.Subscriber._next (Subscriber.js:125)ErrorHandler.handleError @ error_handler.js:51
zone.js:355Unhandled Promise rejection: Cannot read property 'provider' of null ; Zone: <root> ; Task: Promise.then ; Value: TypeError: Cannot read property 'provider' of null(…) TypeError: Cannot read property 'provider' of null
    at MapSubscriber.project (http://localhost:4200/main.bundle.js:35342:83)
    at MapSubscriber._next (http://localhost:4200/main.bundle.js:4171:35)
    at MapSubscriber.Subscriber.next (http://localhost:4200/main.bundle.js:395:18)
    at DistinctUntilChangedSubscriber._next (http://localhost:4200/main.bundle.js:25485:30)
    at DistinctUntilChangedSubscriber.Subscriber.next (http://localhost:4200/main.bundle.js:395:18)
    at MapSubscriber._next (http://localhost:4200/main.bundle.js:4177:26)
    at MapSubscriber.Subscriber.next (http://localhost:4200/main.bundle.js:395:18)
    at MapSubscriber._next (http://localhost:4200/main.bundle.js:4177:26)
    at MapSubscriber.Subscriber.next (http://localhost:4200/main.bundle.js:395:18)
    at RefCountSubscriber.Subscriber._next (http://localhost:4200/main.bundle.js:431:26)consoleError @ zone.js:355
zone.js:357Error: Uncaught (in promise): TypeError: Cannot read property 'provider' of null
    at resolvePromise (http://localhost:4200/main.bundle.js:93214:31)
    at http://localhost:4200/main.bundle.js:93191:13
    at ZoneDelegate.invoke (http://localhost:4200/main.bundle.js:92988:28)
    at Zone.run (http://localhost:4200/main.bundle.js:92881:43)
    at http://localhost:4200/main.bundle.js:93247:57
    at ZoneDelegate.invokeTask (http://localhost:4200/main.bundle.js:93021:37)
    at Zone.runTask (http://localhost:4200/main.bundle.js:92921:47)
    at drainMicroTaskQueue (http://localhost:4200/main.bundle.js:93153:35)consoleError @ zone.js:357 

问题:

这个错误对我来说毫无意义。它完全无用且不可读。 我很幸运看到了这条线(有时我没有得到任何指示错误在哪里):at MapSubscriber.project (auth.effects.ts:80) - 这条线是唯一有助于了解如何修复该错误的线。 试图理解堆栈跟踪将毫无意义,因为它都是 rxjs 堆栈跟踪。

我的问题:

我想知道我的代码的堆栈跟踪。这可能吗?

    在我的代码中订阅该 observable 发生的位置。 如果它是来自 ngrx 的 observable,那么在我的代码中,有人调度了导致错误的操作。

关于如何使用 rxjs 调试异步代码然后修复这个特定错误的更一般的问题。

【问题讨论】:

【参考方案1】:

它发生在您提供给map 运算符的投影方法中。线索在你的堆栈顶部。 MapSubscriber.project.

基本上,您从顶部读取堆栈跟踪。最重要的调用是错误被抛出(或重新抛出)的地方。

在 RxJS 5 中,每个操作符通常有两到三个调用。每个运营商都有一个以它命名的订户来完成这项工作。 MapSubscriber.Subscriber.nextMapSubscriber._next

【讨论】:

感谢您提供的信息。基本上你说没有办法知道在我的代码中有人订阅了导致错误的可观察对象? @StavAlfi 发生错误时,不可能有不在堆栈上的代码堆栈跟踪。当您调用subscribe 时,您正在侦听要发出的事件。如果 when 您调用 subscribe 时它没有立即出错,则该调用不在调用堆栈上。如果您的可观察链中发生错误(在这种情况下,您提供给地图操作员的项目功能)它永远不会到达您的观察者;您提供订阅的回调,所以它也不在堆栈上。 好的,谢谢@JayPhelps。我希望你们将构建一个仅包含异步操作的额外堆栈,以便更容易调试和获得更多控制。 你能澄清什么是理想的吗?我们付出了额外的努力,使各种可能的堆栈比 v4 中的堆栈更加清晰,目前尚不清楚我们如何才能显着改进它们。可能有误会? 当您的 Observable 发射项目时,该堆栈与您通过 observable.debounceTime(100).map(i =&gt; i + 1) 等运算符定义流的堆栈无关。当您调用运算符时,它基本上是设置“管道”和操作符就像指令一样,告诉 Rx 为每个发出的项目执行此操作,无论何时它们到达。这与数组方法array.map(i =&gt; i + 1) 不同,因为使用数组您正在处理值现在,因为它们同步存在。而您的 Observable 发出的项目 [通常] 在未来出现,异步。

以上是关于使用 rxjs 时如何获取错误的堆栈跟踪?的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat 启动日志 - 严重:错误 filterStart 如何获取堆栈跟踪?

如何从像 Asp.Net 这样的堆栈跟踪中获取“源错误”?

使用 sbt 和 testng 时,如何获取测试中抛出的异常的完整堆栈跟踪?

如何从 obj-c / ios 中的堆栈跟踪中获取源代码行

抛出异常时如何获取 JavaScript 堆栈跟踪?

从核心转储中获取堆栈跟踪