Как получить трассировку стека ошибки при использовании rxjs?

#javascript #angular #google-chrome-devtools #rxjs #angular-cli

#javascript #angular #google-chrome-devtools #rxjs #angular-cli

Вопрос:

Я использую angular-cli для создания небольшого веб-приложения angular2 и отлаживаю его с помощью 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.

Мой вопрос:

Я хотел бы знать трассировку стека моего кода. Возможно ли это?

  1. где в моем коде происходит подписка на это наблюдаемое.
  2. Если это наблюдаемое из ngrx, то где в моем коде кто-то отклонил это действие, которое вызывает ошибку.

Это более общий вопрос о том, как отлаживать асинхронный код с помощью rxjs, а затем исправлять эту конкретную ошибку.

Ответ №1:

Это произошло в методе проекции, который вы предоставили map оператору. Ключ находится в верхней части вашего стека. MapSubscriber.project .

В основном вы читаете трассировки стека сверху. Самый верхний вызов — это то, где ошибка была выдана (или повторно отброшена).

В RxJS 5 обычно выполняется два или три вызова для каждого оператора. У каждого оператора есть подписчик, названный в его честь, который выполняет работу. MapSubscriber.Subscriber.next MapSubscriber._next и т. д

Комментарии:

1. спасибо за информацию. По сути, вы говорите, что нет способа узнать, где в моем коде кто-то подписался на это наблюдаемое, которое вызывает ошибку?

2. @StavAlfi невозможно иметь трек стека кода, которого нет в стеке при возникновении ошибки. При вызове вы subscribe прослушиваете события, которые будут отправлены. Если при вызове subscribe сразу не возникает ошибка, этот вызов не находится в стеке вызовов. Если ошибка возникает внутри вашей наблюдаемой цепочки (в данном случае вашей проектной функции, которую вы предоставляете оператору map), она никогда не достигает вашего наблюдателя; обратный вызов, который вы предоставили для подписки, так что, опять же, его тоже нет в стеке.

3. Хорошо, спасибо @JayPhelps. Я надеюсь, что вы, ребята, создадите дополнительный стек, содержащий только асинхронные операции, чтобы его было легче отлаживать и получать больше контроля.

4. Можете ли вы уточнить, что было бы идеально? Мы очень усердно работали, чтобы сделать различные возможные стеки значительно более понятными, чем они были в версии 4, и неясно, как мы могли бы их значительно улучшить. Возможно, это недоразумение?

5. Когда ваш наблюдаемый объект выдает элементы, этот стек не связан со стеком, в котором вы определили поток с помощью таких операторов, как observable.debounceTime(100).map(i => i 1) etc. Когда вы вызываете операторы, это в основном настройка «каналов», а операторы похожи на инструкции, указывающие Rx делать это для каждого отправленного элемента, когда бы они ни поступали. Это отличается от методов массива array.map(i => i 1) , потому что с массивом вы работаете со значениями прямо сейчас , потому что они существуют синхронно. В то время как элементы, которые ваш наблюдаемый выдает [обычно], приходят в будущем, асинхронно.