6

I'm using angular-cli to build a small angular2 web app and I'm debugging with chrome dev-tools.

Clearly I'm doing something wrong if I need to guess each time where is the source of the error and what is the stack-trace of that error.

Take for example this error:

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 

The problem:

This errors means nothing to me. It's completely uselss and un readble. I got lucky that I saw this line (sometimes I dont get any indication where the error is): at MapSubscriber.project (auth.effects.ts:80) - This line is the only line that usefull here to get some idea how to fix that bug. Trying to understand the stack-trace will be pointless because its all rxjs stack-trace.

My question:

I would like to know my code's stack-trace. Is that possible?

  1. where in my code the subscription to that observable happens.
  2. If its an observable from ngrx, then where in my code someone dispanched that action that causes the error.

Its more general question about how to debug async code with rxjs then fixing this specific bug.

1 Answer 1

1

It happened in the projection method you provided to a map operator. The clue is at the top of your stack. MapSubscriber.project.

Basically you read stack traces from the top. The top most call is where the error was thrown (or rethrown).

In RxJS 5, there are usually two or three calls per operator. Each operator has a subscriber named after it that does the work. MapSubscriber.Subscriber.next MapSubscriber._next etc

Sign up to request clarification or add additional context in comments.

6 Comments

thanks for the information. Basicly you saying that there is no way to know where in my code someone subscribed to that observable that causes the error?
@StavAlfi it's impossible to have a stack track of code that isn't on the stack when the error occurs. When you call subscribe, you're listening for events to be emitted. If it doesn't immediately error when you call subscribe, that invocation is not on the call stack. If an error occurs inside your observable chain (in this case, your project function you provide to the map operator) it never reaches your observer; the callback you provided to subscribe so again it's not on the stack either.
Okay thanks @JayPhelps. I hope you guys will build an extra stack containing only the async opertions so it will be easier to debug and get more control.
Can you clarify what would be ideal? We've worked extra hard to make the various possible stacks significantly more clear than they were in v4, and it's not clear how we could improve them significantly. Perhaps there's misunderstanding?
When your Observable is emitting items, that stack is unrelated to the stack of where you defined the stream via operators like observable.debounceTime(100).map(i => i + 1) etc. When you invoke operators, it's basically setting up "pipes" and the operators are like instructions, telling Rx to do this for each item emitted, whenever they arrive. This differs from array methods array.map(i => i + 1) because with an array you're working on the values right now because they exist, synchronously. Whereas the items your Observable emits [usually] come in the future, async.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.