Giter VIP home page Giter VIP logo

rxjs-spy's Introduction

rxjs-spy

GitHub License NPM version Downloads Build status dependency status devDependency Status peerDependency Status Greenkeeper badge

What is it?

rxjs-spy is a debugging library for RxJS.

Why might you need it?

The usual approach to debugging RxJS-based code involves sprinkling do operators and logging throughout composed observables. That's something that I find tedious, so I wrote this library and implemented an unobtrusive mechanism for identifying observables and logging and inspecting observable subscriptions.

If you, too, are looking for a less painful RxJS debugging experience, you might find this library useful. The engineers at Slack have adopted rxjs-spy and have this to say about it:

You might be like, "[...] but aren't Observables impossible to debug?" And you'd have been mostly right less than a year ago. But this is JavaScript and in JavaScript, the only const is change. rxjs-spy makes debugging (i.e. logging and visualizing) streams as simple as adding a tag. A tagged stream can be monitored, paused, and replayed, right from the console.

For more detail regarding how the library works and what it can do, you can have a look at:

Install

Install the package using NPM:

npm install rxjs-spy --save-dev

And import the functions for use with TypeScript or ES2015:

import { create } from "rxjs-spy";
const spy = create();

Or require the module for use with Node or a CommonJS bundler:

const { create } = require("rxjs-spy");
const spy = create();

Or include the UMD bundle for use as a script:

<script src="https://unpkg.com/rxjs@6/bundles/rxjs.umd.min.js"></script>
<script src="https://unpkg.com/rxjs-spy@7/bundles/rxjs-spy.min.umd.js"></script>
<script>
const { create } = rxjsSpy;
create();
</script>

Core concepts

rxjs-spy introduces a tag operator that can be used to identify observables. It attaches a string tag to an observable; it performs no additional processing and does not alter the observable's behaviour or value in any way.

The tag operator can be used with pipe:

import { tag } from "rxjs-spy/operators/tag";
const source = Observable.of("some-value").pipe(tag("some-tag"));

The API's methods are tag-based and tags can be matched using explicit literals, regular expressions or function predicates. For example, logging for the above tag could be enabled like this:

import { create } from "rxjs-spy";
const spy = create();
spy.log("some-tag");

// Or like this:
spy.log(/^some-tag$/);

// Or like this:
spy.log(tag => tag === "some-tag");

rxjs-spy exposes a module API intended to be called from code and a console API - via the spy global - intended for interactive use via the browser's console.

Module API

The methods in the module API are callable via imports, requires or the UMD rxjsSpy global. Most methods return a teardown function that will undo the API method's action when called.

create

function create(options: {
    [key: string]: any,
    audit?: number,
    defaultLogger?: PartialLogger,
    defaultPlugins?: boolean,
    warning?: boolean
} = {}): Teardown

Calling create attaches the spy to Observable.prototype.subscribe and returns the following interface:

interface Spy {
  readonly tick: number;
  debug(match: Match, ...notifications: Notification[]): Teardown;
  find<T extends Plugin>(ctor: Ctor<T>): T | undefined;
  findAll<T extends Plugin>(ctor: Ctor<T>): T[];
  findAll(): Plugin[];
  flush(): void;
  let(match: Match, select: (source: Observable<any>) => Observable<any>, options?: Options): Teardown;
  log(match: Match, partialLogger?: PartialLogger): Teardown;
  log(partialLogger?: PartialLogger): Teardown;
  pause(match: Match): Deck;
  plug(...plugins: Plugin[]): Teardown;
  show(match: Match, partialLogger?: PartialLogger): void;
  show(partialLogger?: PartialLogger): void;
  stats(partialLogger?: PartialLogger): void;
  teardown(): void;
  unplug(...plugins: Plugin[]): void;
}

By default, create will wire up the snapshotting plugin and numerous others. However, if the defaultPlugins option is specified as false, no plugins will be wired up and the caller can wire up plugins individually using the plug method. For example:

import { create } from "rxjs-spy";
import { GraphPlugin, SnapshotPlugin } from "rxjs-spy/plugin";
const spy = create({ defaultPlugins: false });
spy.plug(
  new GraphPlugin({ keptDuration: -1 }),
  new SnapshotPlugin(spy, { keptValues: 1 })
);

If the audit option is specified, the logging of notifications will be audited within the specified (milliseconds) duration. Each notification source will only be logged once in each duration and the number of ignored notifications (if any) will be included in the console output. This can be useful for logging high-frequency observables. audit defaults to zero - i.e. no auditing.

Options passed to create are forwarded to the plugins, so the following can be specified:

Option Type Description Default
keptDuration number The number of milliseconds for which the subscription graph and snapshots should be kept after unsubscription occurs. 30000
keptValues number The maximum number of values that should be kept in a snapshot. 4
sourceMaps boolean Whether or not the StackTracePlugin should use source maps. false

This method returns a teardown function.

show

interface Spy {
  show(
    match: string | RegExp | MatchPredicate | Observable<any>,
    partialLogger: PartialLogger = console
  ): void;
  show(
    partialLogger: PartialLogger = console
  ): void;
}

show will log information regarding the matching observables to the console or to the specified logger. If no match is specified, all tagged observables will be logged.

The logged information is retrieved from the most recent snapshot, so if snapshotting is not enabled, an error will be thrown.

log

interface Spy {
  log(
    match: string | RegExp | MatchPredicate | Observable<any>,
    partialLogger: PartialLogger = console
  ): Teardown;
  log(
    partialLogger: PartialLogger = console
  ): Teardown;
}

Wires up an instance of the log plugin for matching observables. If no match is specified, all tagged observables will be logged.

All subscribe, next, complete, error and unsubscribe notifications will be logged to the console or to the specified logger.

This method returns a teardown function.

pause

interface Spy {
  pause(
    match: string | RegExp | MatchPredicate | Observable<any>
  ): Deck;
}

Wires up an instance of the pause plugin for matching observables.

All subscriptions to matching observables will be placed into a paused state and notifications that would otherwise be emitted will be buffered inside the plugin.

This method returns a Deck instance that can be used to resume and pause the observables.

interface Deck {
  readonly paused: boolean;
  clear(): void;
  log(partialLogger: PartialLogger = console): void;
  pause(): void;
  resume(): void;
  skip(): void;
  step(): void;
  teardown(): void;
}

Calling step will release a single paused notification. The other methods to what their names suggest. Calling resume will play all buffered notifications before resuming.

let

interface Spy {
  let(
    match: string | RegExp | MatchPredicate | Observable<any>,
    select: (source: Observable<any>) => Observable<any>,
    options?: Options
  ): Teardown;
}

Wires up an instance of the let plugin for matching observables.

This is equivalent to the let operator. All subscriptions to matching observables will instead be made to the observable returned by the specified select function.

If complete option is false, completion notifications received from the selected observable will not be forwarded to subscribers.

This method returns a teardown function.

debug

interface Spy {
  debug(
    match: string | RegExp | MatchPredicate | Observable<any>,
    ...notifications: ("complete" | "error" | "next" | "subscribe" | "unsubscribe")[]
  ): Teardown;
}

Wires up an instance of the debug plugin for matching observables.

Whenever one of the specified notifications occurs, a debugger statement in the plugin will pause execution. If no notifications are specified in the call, execution will be paused when any of the notifications occurs.

This method returns a teardown function.

flush

interface Spy {
  flush(): void;
}

Calling flush will see flush called on each plugin.

If snapshotting is enabled, calling flush will release excess values and completed or errored obervables from within snapshots.

plug

interface Spy {
  plug(...plugins: Plugin[]): Teardown;
}

Wires up the specified plugin(s) and returns a teardown function.

unplug

interface Spy {
  unplug(...plugins: Plugin[]): void;
}

Removes the specified plugin(s).

find

interface Spy {
  find<T extends Plugin>(constructor: { new (...args: any[]): T }): T | undefined;
}

Returns the first plugin matching the specified constructor/class.

findAll

interface Spy {
  findAll<T extends Plugin>(constructor: { new (...args: any[]): T }): T[];
  findAll(): T[];
}

Returns all plugins matching the specified constructor/class. Or all plugins of no constructor is specified.

stats

interface Spy {
  stats(partialLogger: PartialLogger = console): void;
}

Writes, to the console, counts of the number of notifications, etc.

teardown

interface Spy {
  teardown(): void;
}

Tears down the spy.

detect

function detect(id: string): void;

Writes, to the console, any subscriptions and unsubscriptions that have occurred since the previous detect call with the specified id.

The detect method is implemented so that it can be imported and called regardless of whether or not the spy is configured. That is, calls can be left in production code, as they become no-ops. It should be imported like this:

import { detect } from "rxjs-spy/detect";

Console API

The methods in the console API are callable via the spy global and are intended to be used interactively in the browser's console.

They are identical to the methods in the spy instances created using the module API except for the fact that they do not return teardown functions. Instead, calls can be undone using the undo API method.

undo

function undo(...calls: number[]): void

When called without arguments, the undo method will display in the console a list of the rxjs-spy calls that can be undone.

Calls are listed against a call number and one or more of those numbers can be passed to undo to undo specific calls.

Undoing a spy call will undo all calls.

deck

function deck(call?: number): Deck | undefined

In the console, it's easy to forget to use a variable to capture the Deck returned by a call to pause. In those situations, you can call the deck method without an argument to see a list of numbered pause calls. Calling deck again, passing a call number, will return the Deck associated with the specified pause call.

rxjs-spy's People

Contributors

cartant avatar greenkeeper[bot] avatar hariseldon78 avatar zaripych avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rxjs-spy's Issues

Feature Request: Add esm support

Add esm output and module mainField.

I'm using Angular 10 and see warning:

WARNING in my-lib depends on 'rxjs-spy/operators'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies

Hangs IE11

In an Angular 6.1.9 app, we added the following to app.module.ts:

import { create as rxjsCreate } from 'rxjs-spy';
rxjsCreate(); // Start rxjs-spy

We find rxjs-spy works great in all other browsers, but in IE11, the browser hangs when attempting to load the app. The screen is blank and IE shows an error message at the bottom:

localhost is not responding due to a long-running script

If I wait for about 10 minutes, the app will finally show up. But then each navigation within the app takes 1-2 minutes to complete and even popping up a modal takes 10 seconds. These should be near-instantaneous.

If I comment out the rxjsCreate() call, the app runs normally.

Yes, I know IE11 is slow. But what is rxjs-spy doing that slows things down so drastically?

Diagnosing `RangeError: Maximum Call Stack Size Exceeded` using RxJS Spy

Hi,
I'm not sure this is a bug with RxJS Spy.

We are running RxJs-Spy on our DEV environment server for additional logging purposes and getting RangeError intermittently which causes a crash and makes our server restart. With mostly RxJS and Spy related difficult to diagnose operators-only stack trace. :)

I seem to be able to reproduce the issue only when RxJS Spy is enabled. It is very well possible that due to Spy-related hooks the stack trace really increases in size - naturally, and it just opens-up the underlying issue in our code.

I can connect with the Chrome debugger and break when the exception happens, but at this stage it seems to be too late and I can do nothing to diagnose the state of the app. Moving through stack trace and inspecting variables just doesn't work.

My understanding of the stack trace is that the culprit might be mergeMap operator which seem to increase the stack indefinitely - as I can see it in the trace again and again. A "complete" followed by a "next" followed by another "complete" followed by another "next" ... etc.

I looked at all places where we use the mergeMap operator and the source observable at those places is usually a single element emitters. Those places where it is not a single element are not related to the scenario that cause the issue. And tag-ging those places doesn't open up any new info.

The cycle plugin doesn't seem to be logging any warnings. Is there any other particular way we could use RxJS Spy to diagnose this kind of issue?

Thank you very much!

The full stack trace:

(anonymous) (hostReportError.ts:7)
ontimeout (timers.js:436)
tryOnTimeout (timers.js:300)
listOnTimeout (timers.js:263)
processTimers (timers.js:223)
Timeout (async)
init (internal/inspector_async_hook.js:27)
emitInitNative (internal/async_hooks.js:137)
emitInitScript (internal/async_hooks.js:336)
initAsyncResource (internal/timers.js:50)
Timeout (internal/timers.js:82)
setTimeout (timers.js:414)
hostReportError (hostReportError.ts:7)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:271)
SafeSubscriber.complete (Subscriber.ts:251)
Subscriber._complete (Subscriber.ts:148)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (subscribeToArray.ts:11)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
MergeMapSubscriber.notifyComplete (mergeMap.ts:170)
InnerSubscriber._complete (InnerSubscriber.ts:26)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (spy-core.js:472)
notify_ (spy-core.js:443)
complete (spy-core.js:472)
complete (spy-core.js:488)
wrappedComplete (Subscriber.ts:248)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.complete (Subscriber.ts:251)
Subscriber._complete (Subscriber.ts:148)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (subscribeToArray.ts:11)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
MergeMapSubscriber.notifyComplete (mergeMap.ts:170)
InnerSubscriber._complete (InnerSubscriber.ts:26)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (spy-core.js:472)
notify_ (spy-core.js:443)
complete (spy-core.js:472)
complete (spy-core.js:488)
wrappedComplete (Subscriber.ts:248)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.complete (Subscriber.ts:251)
Subscriber._complete (Subscriber.ts:148)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (subscribeToArray.ts:11)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
MergeMapSubscriber.notifyComplete (mergeMap.ts:170)
InnerSubscriber._complete (InnerSubscriber.ts:26)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (spy-core.js:472)
notify_ (spy-core.js:443)
complete (spy-core.js:472)
complete (spy-core.js:488)
wrappedComplete (Subscriber.ts:248)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.complete (Subscriber.ts:251)
Subscriber._complete (Subscriber.ts:148)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (subscribeToArray.ts:11)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
MergeMapSubscriber.notifyComplete (mergeMap.ts:170)
InnerSubscriber._complete (InnerSubscriber.ts:26)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (spy-core.js:472)
notify_ (spy-core.js:443)
complete (spy-core.js:472)
complete (spy-core.js:488)
wrappedComplete (Subscriber.ts:248)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.complete (Subscriber.ts:251)
Subscriber._complete (Subscriber.ts:148)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (subscribeToArray.ts:11)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
MergeMapSubscriber.notifyComplete (mergeMap.ts:170)
InnerSubscriber._complete (InnerSubscriber.ts:26)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (spy-core.js:472)
notify_ (spy-core.js:443)
complete (spy-core.js:472)
complete (spy-core.js:488)
wrappedComplete (Subscriber.ts:248)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.complete (Subscriber.ts:251)
Subscriber._complete (Subscriber.ts:148)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (subscribeToArray.ts:11)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
MergeMapSubscriber.notifyComplete (mergeMap.ts:170)
InnerSubscriber._complete (InnerSubscriber.ts:26)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (spy-core.js:472)
notify_ (spy-core.js:443)
complete (spy-core.js:472)
complete (spy-core.js:488)
wrappedComplete (Subscriber.ts:248)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.complete (Subscriber.ts:251)
Subscriber._complete (Subscriber.ts:148)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (subscribeToArray.ts:11)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
MergeMapSubscriber.notifyComplete (mergeMap.ts:170)
InnerSubscriber._complete (InnerSubscriber.ts:26)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (spy-core.js:472)
notify_ (spy-core.js:443)
complete (spy-core.js:472)
complete (spy-core.js:488)
wrappedComplete (Subscriber.ts:248)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.complete (Subscriber.ts:251)
Subscriber._complete (Subscriber.ts:148)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (subscribeToArray.ts:11)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
MergeMapSubscriber.notifyComplete (mergeMap.ts:170)
InnerSubscriber._complete (InnerSubscriber.ts:26)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (spy-core.js:472)
notify_ (spy-core.js:443)
complete (spy-core.js:472)
complete (spy-core.js:488)
wrappedComplete (Subscriber.ts:248)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.complete (Subscriber.ts:251)
Subscriber._complete (Subscriber.ts:148)
Subscriber.complete (Subscriber.ts:126)
(anonymous) (subscribeToArray.ts:11)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
MergeMapSubscriber.notifyComplete (mergeMap.ts:170)
InnerSubscriber._complete (InnerSubscriber.ts:26)
Subscriber.complete (Subscriber.ts:126)
Promise.then (async)
(anonymous) (subscribeToPromise.ts:5)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
IgnoreElementsOperator.call (ignoreElements.ts:41)
Observable.subscribe (Observable.ts:214)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
(anonymous) (defer.ts:65)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (subscribeToArray.ts:9)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
MergeMapOperator.call (mergeMap.ts:100)
Observable.subscribe (Observable.ts:214)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
MergeMapSubscriber.notifyNext (mergeMap.ts:162)
InnerSubscriber._next (InnerSubscriber.ts:17)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
FilterSubscriber._next (filter.ts:101)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
MapSubscriber._next (map.ts:89)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
MergeMapSubscriber.notifyNext (mergeMap.ts:162)
InnerSubscriber._next (InnerSubscriber.ts:17)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (subscribeToArray.ts:9)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
SkipWhileSubscriber._next (skipWhile.ts:52)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
ScanSubscriber._tryNext (scan.ts:119)
ScanSubscriber._next (scan.ts:106)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
ReplaySubject._subscribe (ReplaySubject.ts:80)
Observable._trySubscribe (Observable.ts:238)
Subject._trySubscribe (Subject.ts:116)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
ScanOperator.call (scan.ts:75)
Observable.subscribe (Observable.ts:214)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
SkipWhileOperator.call (skipWhile.ts:27)
Observable.subscribe (Observable.ts:214)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
MergeMapOperator.call (mergeMap.ts:100)
Observable.subscribe (Observable.ts:214)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
TagOperator.call (tag.js:14)
Observable.subscribe (Observable.ts:214)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
MapOperator.call (map.ts:59)
Observable.subscribe (Observable.ts:214)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
FilterOperator.call (filter.ts:71)
Observable.subscribe (Observable.ts:214)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
TickObject (async)
init (internal/inspector_async_hook.js:27)
emitInitNative (internal/async_hooks.js:137)
emitInitScript (internal/async_hooks.js:336)
TickObject (internal/process/next_tick.js:86)
nextTick (internal/process/next_tick.js:117)
resume (_stream_readable.js:922)
Readable.resume (_stream_readable.js:913)
processCB (processor.js:458)
(anonymous) (processor.js:213)
proto._getFfmpegPath (capabilities.js:90)
proto._spawnFfmpeg (processor.js:132)
(anonymous) (processor.js:437)
wrapper (async.js:272)
next (async.js:4584)
(anonymous) (async.js:325)
(anonymous) (processor.js:363)
proto.availableEncoders.proto.getAvailableEncoders (capabilities.js:457)
(anonymous) (processor.js:351)
nextTask (async.js:4578)
next (async.js:4586)
(anonymous) (async.js:325)
(anonymous) (processor.js:346)
nextTask (async.js:4578)
next (async.js:4586)
(anonymous) (async.js:325)
(anonymous) (processor.js:333)
nextTask (async.js:4578)
next (async.js:4586)
(anonymous) (async.js:325)
(anonymous) (processor.js:304)
nextTask (async.js:4578)
next (async.js:4586)
(anonymous) (async.js:325)
wrapper (async.js:272)
next (async.js:4584)
(anonymous) (async.js:325)
(anonymous) (capabilities.js:661)
nextTask (async.js:4578)
next (async.js:4586)
(anonymous) (async.js:325)
proto.availableEncoders.proto.getAvailableEncoders (capabilities.js:457)
(anonymous) (capabilities.js:618)
nextTask (async.js:4578)
next (async.js:4586)
(anonymous) (async.js:325)
(anonymous) (capabilities.js:613)
nextTask (async.js:4578)
next (async.js:4586)
(anonymous) (async.js:325)
proto.availableFormats.proto.getAvailableFormats (capabilities.js:513)
(anonymous) (capabilities.js:568)
nextTask (async.js:4578)
waterfall (async.js:4589)
awaitable(waterfall) (async.js:208)
proto._checkCapabilities (capabilities.js:565)
(anonymous) (processor.js:298)
nextTask (async.js:4578)
waterfall (async.js:4589)
awaitable(waterfall) (async.js:208)
proto._prepare (processor.js:295)
proto.exec.proto.execute.proto.run (processor.js:431)
pipe.subscribe.state (index.ts:187)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
SwitchMapSubscriber.notifyNext (switchMap.ts:166)
InnerSubscriber._next (InnerSubscriber.ts:17)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
MapSubscriber._next (map.ts:89)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
TakeSubscriber._next (take.ts:92)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
Subject.next (Subject.ts:70)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
MergeMapSubscriber.notifyNext (mergeMap.ts:162)
InnerSubscriber._next (InnerSubscriber.ts:17)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
MergeMapSubscriber.notifyNext (mergeMap.ts:162)
InnerSubscriber._next (InnerSubscriber.ts:17)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
notify_ (spy-core.js:443)
next (spy-core.js:478)
next (spy-core.js:526)
SafeSubscriber.__tryOrUnsub (Subscriber.ts:265)
SafeSubscriber.next (Subscriber.ts:207)
Subscriber._next (Subscriber.ts:139)
Subscriber.next (Subscriber.ts:99)
(anonymous) (subscribeToArray.ts:9)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
subscribeToResult (subscribeToResult.ts:26)
MergeMapSubscriber._innerSub (mergeMap.ts:148)
MergeMapSubscriber._tryNext (mergeMap.ts:141)
MergeMapSubscriber._next (mergeMap.ts:125)
Subscriber.next (Subscriber.ts:99)
(anonymous) (spy-core.js:478)
Promise.then (async)
(anonymous) (subscribeToPromise.ts:5)
Observable._trySubscribe (Observable.ts:238)
Observable.subscribe (Observable.ts:219)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
SwitchMapOperator.call (switchMap.ts:101)
Observable.subscribe (Observable.ts:214)
(anonymous) (spy-core.js:549)
notify_ (spy-core.js:443)
SpyCore.coreSubscribe_ (spy-core.js:548)
voice (index.ts:86)
handle (layer.js:95)
next (route.js:137)
dispatch (route.js:112)
handle (layer.js:95)
(anonymous) (index.js:281)
param (index.js:354)
param (index.js:365)
process_params (index.js:410)
next (index.js:275)
cors (index.js:188)
(anonymous) (index.js:224)
originCallback (index.js:214)
(anonymous) (index.js:219)
optionsCallback (index.js:199)
corsMiddleware (index.js:204)
handle (layer.js:95)
trim_prefix (index.js:317)
(anonymous) (index.js:284)
process_params (index.js:335)
next (index.js:275)
expressInit (init.js:40)
handle (layer.js:95)
trim_prefix (index.js:317)
(anonymous) (index.js:284)
process_params (index.js:335)
next (index.js:275)
query (query.js:45)
handle (layer.js:95)
trim_prefix (index.js:317)
(anonymous) (index.js:284)
process_params (index.js:335)
next (index.js:275)
handle (index.js:174)
handle (application.js:174)
app (express.js:39)
emit (events.js:189)
parserOnIncoming (_http_server.js:676)
parserOnHeadersComplete (_http_common.js:109)
HTTPPARSER (async)
init (internal/inspector_async_hook.js:27)
emitInitNative (internal/async_hooks.js:137)
connectionListenerInternal (_http_server.js:344)
defaultTriggerAsyncIdScope (internal/async_hooks.js:294)
connectionListener (_http_server.js:321)
emit (events.js:189)
onconnection (net.js:1510)
TCPSERVERWRAP (async)
init (internal/inspector_async_hook.js:27)
emitInitNative (internal/async_hooks.js:137)
createServerHandle (net.js:1194)
setupListenHandle (net.js:1237)
listenInCluster (net.js:1318)
Server.listen (net.js:1405)
Promise (start.ts:132)
start (start.ts:122)
await in start (async)
(anonymous) (server.ts:4)
Module._compile (internal/modules/cjs/loader.js:701)
Module._extensions..js (internal/modules/cjs/loader.js:712)
Module.load (internal/modules/cjs/loader.js:600)
tryModuleLoad (internal/modules/cjs/loader.js:539)
Module._load (internal/modules/cjs/loader.js:531)
Module.runMain (internal/modules/cjs/loader.js:754)
startup (internal/bootstrap/node.js:283)
bootstrapNodeJSCore (internal/bootstrap/node.js:622)

Regarding onScroll

I want to make #leftside div move from top-to-bottom and #rightside div move from bottom to top onscroll.. How I'll be able to do it ? Do i need to use onscoll(); ?

Version 10 of node.js has been released

Version 10 of Node.js (code name Dubnium) has been released! 🎊

To see what happens to your code in Node.js 10, Greenkeeper has created a branch with the following changes:

  • Added the new Node.js version to your .travis.yml

If you’re interested in upgrading this repo to Node.js 10, you can open a PR with these changes. Please note that this issue is just intended as a friendly reminder and the PR as a possible starting point for getting your code running on Node.js 10.

More information on this issue

Greenkeeper has checked the engines key in any package.json file, the .nvmrc file, and the .travis.yml file, if present.

  • engines was only updated if it defined a single version, not a range.
  • .nvmrc was updated to Node.js 10
  • .travis.yml was only changed if there was a root-level node_js that didn’t already include Node.js 10, such as node or lts/*. In this case, the new version was appended to the list. We didn’t touch job or matrix configurations because these tend to be quite specific and complex, and it’s difficult to infer what the intentions were.

For many simpler .travis.yml configurations, this PR should suffice as-is, but depending on what you’re doing it may require additional work or may not be applicable at all. We’re also aware that you may have good reasons to not update to Node.js 10, which is why this was sent as an issue and not a pull request. Feel free to delete it without comment, I’m a humble robot and won’t feel rejected 🤖


FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

console warning: cycle-plugin.js:49 Cyclic next detected

Worrying console message

cycle-plugin.js:49 Cyclic next detected; type = subject; value = Scroll(anchor: 'null', position: 'null'); subscribed at
RouterScroller.push../node_modules/@angular/router/fesm5/router.js.RouterScroller.createScrollEvents()@http://localhost:5009/vendor.js:73846:35
RouterScroller.push../node_modules/@angular/router/fesm5/router.js.RouterScroller.init()@http://localhost:5009/vendor.js:73841:46
RouterInitializer.push../node_modules/@angular/router/fesm5/router.js.RouterInitializer.bootstrapListener()@http://localhost:5009/vendor.js:74223:24
{anonymous}()@http://localhost:5009/vendor.js:43425:56

Evidently something going on in Angular router. Not asking you to fix it.

I am asking what the warning is telling me and what someone (the Angular team?) should do about it.

Trying this promising library for the first time with angular@^6.1.9 and rxjs@^6.3.3

Very slow first request when using rxjs-spy with angular universal

Hello,

I'm having an issue when using rxjs-spy with angular universal (with expressjs).
The first request to the server is very slow and can trigger a 504 Bad Gateway.

This warning message appears in the logs, but according to @cartant it can be ignored.

Value passed as error notification is not an Error instance = NoMatch {
segmentGroup:
UrlSegmentGroup {
segments: [ [Object] ],
children: {},
parent: UrlSegmentGroup { segments: [], children: [Object], parent: null } } }

When removing all occurrences of rxjs-spy the app response time is fast.

[question] What's the overhead of having spy.create() in production?

Trying to decide whether to enable rxjs-spy in production. Ideally we would like to have it there in order to inspect our streams, but it doesn't say much in the docs about how significant the overhead is.

The only code that would run in production is spy.create() and tag() on streams, but as far as I understand rxjs-spy patches Observable.subscribe, so perhaps this isn't very desirable.

Any thoughts on this? :-)

We've tried exposing spy.create in production, but the issue then is that if we create the spy later, we lose out on tagging a lot of streams that have already been created.

Using <rxjs-spy> with SystemJS loader

I tried to use rxjs-spy with Angular app 5.1.0 which is using SystemJS 0.20.19 loader but with no luck. It seams that this lib is very prommising so I would like to go much more deeply. But just for the simple imports ...

import { create } from 'rxjs-spy/spy-factory';
const spy = create();
import { tag } from 'rxjs-spy/operators/tag';

I tried these ways to config relevant part is systemjs.config.js:

1) Standard way ... loading each JS file separately ...

paths: {'npm:': './node_modules/'},
map: {
	...
	'rxjs-spy': 'npm:rxjs-spy',
},
packages: {
	...
	'rxjs-spy': {
		defaultExtension: 'js'
	}
}

... all files loaded successfully except plugin.js:
Fetch finished loading: GET "http://localhost:8080/node_modules/rxjs-spy/spy-factory.js".
Fetch finished loading: GET "http://localhost:8080/node_modules/rxjs-spy/spy-core.js".
...
Fetch finished loading: GET "http://localhost:8080/node_modules/rxjs-spy/operators/hide.js".
... Unexpected token < Evaluating http://localhost:8080/node_modules/rxjs-spy/plugin.js

2) Re-bundling the lib ... loading all things in one step = preferred way ... using ...

bundles: {
	"assets/rxjs-spy-bundle/RxSpy.min.js": [
		"rxjs-spy/*",
		"rxjs-spy/add/operator/*",
		"rxjs-spy/devtools/*",
		"rxjs-spy/operator/*",
		"rxjs-spy/operators/*",
		"rxjs-spy/plugin/*"
	]
}

and re-bundling via Gulp script:

gulp.task('rxjs-spy', function() {
	// SystemJS build options
	var options = {
		normalize: true,
		runtime: false,
		sourceMaps: false,
		sourceMapContents: false,
		minify: true,
		mangle: true
	};
	var builder = new systemjsbuilder('./');
	builder.config({
		paths: {
			"n:*": "node_modules/*",
			"rxjs-spy/*": "node_modules/rxjs-spy/*.js",
		},
		map: {
			"rxjs-spy": "n:rxjs-spy",
		},
		packages: {
			"rxjs-spy": {main: "index.js", defaultExtension: "js"},
		}
	});
	builder.bundle('rxjs-spy', 'assets/rxjs-spy-bundle/RxSpy.min.js', options);
});

... but the Gulp script ended with an error ...
unhandled rejection Error on fetch for rxjs-spy/plugin at file:///C:/Data/Projects/LocalHost/MLC-CSS/node_modules/rxjs-spy/plugin.js

3) Using the UMD lib directly and loaded via <script> tag in index.html ...
It does'n work at all ...
<script src="node_modules/rxjs-spy/bundles/rxjs-spy.min.umd.js" type="text/javascript"></script>
... an error appears:
Error: Unexpected token < Evaluating http://localhost:8080/rxjs-spy/spy-factory

Summary
It looks that there is something wrong with plugin.js because if not .... ways per 1) and 2) would work probably.

Random "Error: Timeout" is triggered in unit test

Environment

Angular CLI: 7.0.6
Node: 8.11.3
OS: win32 x64
Angular: 7.0.4
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.10.6
@angular-devkit/build-angular     0.10.6
@angular-devkit/build-optimizer   0.10.6
@angular-devkit/build-webpack     0.10.6
@angular-devkit/core              7.0.6
@angular-devkit/schematics        7.0.6
@angular/cli                      7.0.6
@ngtools/webpack                  7.0.6
@schematics/angular               7.0.6
@schematics/update                0.10.6
rxjs                              6.3.3
typescript                        3.1.6
webpack                           4.19.1

I can also reproduce this issue on a Linux environment.

Reproduce Steps

  1. Create a standard Angular app using the Angular CLI.
  2. Insert and call create() in the generated app.component.ts.
  3. Execute ng test.

Expected

All tests are run and pass.

Actual

One test failed with timeout error.

Analysis

I discovered this issue while working on my own project. It seems it will cause one unit test case to fail and it alway the same one. But interestingly, if I change the unit test code order, a different one will fail. Also, if I ran only one test case, this issue will not occur.

I know it does not make sense to use this library in unit tests. But it would be better if it does not interfere with unit tests.

Get only "active" subscriptions

I'm getting this list of subscribers:

image

As you can see, State is incomplete and Unsubscribed is true. What does it mean? All subscriptions are created using async angular pipe.

How could I get only current "active" subscriptions?

And how could I get only last snapshot?

Import error in angular/webpack

Error: node_modules/rxjs-spy/cjs/plugin/snapshot-plugin.d.ts:1:10 - error TS2305: Module '"error-stack-parser"' has no exported member 'StackFrame'.

1 import { StackFrame } from "error-stack-parser";
~~~~~~~~~~

Error: node_modules/rxjs-spy/cjs/plugin/stack-trace-plugin.d.ts:1:10 - error TS2305: Module '"error-stack-parser"' has no exported member 'StackFrame'.

1 import { StackFrame } from "error-stack-parser";
~~~~~~~~~~

"Value passed as error notification is not an Error instance = ..."

What would cause the error from spy-core.js-327?

"Value passed as error notification is not an Error instance = ..."

The only thing I have configured in my Angular app is importing 'create' and setting const of spy = create(); in my main.ts file per the github instructions.

Devtool Tab?

Have you had any interest in a devtools tab? Are you aware of any forks or plugins, similar to a Redux dev tool tab, or VueX dev tool tabs?

Thanks! Great project, by the way!

Invalid count between Subscribes and Unsubscribes

I want to implement an angular component to display in realtime the "live" observable count, but the count doesn't make sense (to me). For example, after a while playing with the app, I get in the console:

Stats
spy-core.js:362 Subscribes = 703
spy-core.js:364 Root subscribes = 70
spy-core.js:367 Leaf subscribes = 210
spy-core.js:370 Flattened subscribes = 163
spy-core.js:372 Unsubscribes = 705
spy-core.js:373 Nexts = 1921
spy-core.js:374 Errors = 20
spy-core.js:375 Completes = 579
spy-core.js:377 Max. depth = 18
spy-core.js:378 Avg. depth = 2.3
spy-core.js:380 Tick = 3928
spy-core.js:381 Timespan = 529001

How it is possible that I have more unsubscribes than subscribes?

The test file https://github.com/cartant/rxjs-spy/blob/master/source/plugin/stats-plugin-spec.ts is quite usefull to understand how things work, but it would be even better with some tests on the impact of errors on Unsubscribes or Completes counts.

Also, according to the test file, Subscribes = Root subscribes + Leaf subscribes + Flattened subscribes, but it doesn't seem to be the case.

Tagging is inconsistent

Is this project not being maintained anymore?

I find that the tag works only sporadically and have not been able to detect a pattern as to when it does and does not.
For example, in the following test:

// -------------------------------------------------------------------------
// rxjs-spy
const spy= create()
spy.log()
it('syncedScrap$ lifetime and shutdown', () => {

  // ---- Setup struct input
  const structScrap$  = new Subject<Partial<Struct_ImageScrap>>()
  mocked(firestoreSyncDocument)
    .mockImplementation((docRef: DocRef) => {

      function d(id: string,
                 struct: Partial<Struct_ImageScrap>,
                 ref: DocRef = { id } as DocRef
      ): DocSnap {
        return ({ id, ref, data: () => struct,} as any) as DocSnap
      }

      if (docRef.id === 'scrap')
        return structScrap$.pipe(
          map(struct => d(docRef.id, struct)),
          tag('structScrap$'),
        )
      return EMPTY
    })

  // ---- Setup Collage producing sync
  const scrap$ = new BehaviorSubject<Scrap|null>(null)
  const s$ = syncedScrap$(firestoreCollageScrap('collage', 'scrap')).pipe(
      tag("syncedScrap$"),
    )
  const subs = s$.subscribe(s => scrap$.next(s))

the tag structScrap$ gets logged but syncedScrap$ does. Am I misunderstanding something?

spy.show() doesn't filter out observables that run in sync

When using spy.show() from the console, observables that run synchronously are not filtered out of the list.

const asyncSub = new AsyncSubject();
asyncSub.next(null);
asyncSub.complete();

asyncSub.pipe(tag('nodelay.1')).subscribe();
asyncSub.pipe(tag('nodelay.2')).subscribe();

asyncSub
	.pipe(
		tag('delay.1'),
		delay(1),
	)
	.subscribe();

asyncSub
	.pipe(
		tag('delay.2'),
		delay(1),
	)
	.subscribe();

spybug

ng add rxjs-spy

Please, add "ng add" support;
Now if i try in ng-generated project:

ng add rxjs-spy

i catch this error:

The package that you are trying to add does not support schematics. You can try using a different version of the package or contact the package author to add ng-add support.

this issue implicitly relates to this issue:

#39

Share operator does not reconnect to source observable when rxjs spy is running

Rxjs-spy is not handling connectable observables correctly. This will impact the multicast family of operators, including share.

When a shared observable is completely unsubscribed, then resubscribed later, normally the source observable is resubscribed.
When there is a spy object created, this is not working. The share operator creates an internal subject, I see that is not being unsubscribed as well.

Here is some code that demonstrates the issue. The issue is present if a spy object has been created.

const shared$ = interval(100).pipe(
  share()
);

const a = shared.subscribe(() => log('a'))
setTimeout(() => a.unsubscribe(), 200);  // a logged twice, then the interval() observable is unsubscribed

setTimeout(() => shared.subscribe(() => log('b')),  1000);    //Nothing logged. This should log b repeatedly

Here is a runnable version
https://stackblitz.com/edit/rxjs-spy-share?file=index.ts

detect doesn't work with custom plugin config

detect throws up the warning 'Snapshotting is not enabled.' if you don't use the defaultPlugin setting.

import { create } from 'rxjs-spy';
import {
	GraphPlugin,
	SnapshotPlugin,
	StackTracePlugin,
	StatsPlugin,
} from 'rxjs-spy/plugin';
const spy = create({
	defaultPlugins: false,
	warning: true,
});
spy.plug(
	new StackTracePlugin({ sourceMaps: false }),
	new GraphPlugin({ keptDuration: 15000 }),
	new SnapshotPlugin(spy, { keptValues: 4 }),
	new StatsPlugin(spy),
);
window['spy'].detect();

Auto tagging

I'm starting to explore rxjs-spy for use in a large Angular application. We have about ~1000 components so there's a large number of observables. Prior to discovering rxjs-spy, I was exploring using a Typescript compiler plugin to automatically generate debugging information for each subscription (i.e. name, location, and code of each subscription) and then using that information for leak detection in my tests.

I was thinking about pivoting this code to use rxjs-spy under the covers instead. Is there any downside to automatically adding tag(...) to every subscription? It's relatively straightforward to do in a compiler plugin - the toughest part seems like coming up with a usable name.

Thanks!

RxJS v7 compatibility

After upgrading my code base to v7, I get quite a lot of errors from rxjs-spy, mostly about TypeError: this.destination.next is not a function (with rather weird line number offset, which points to this.destination.complete, rather than .next). However, this error does not prevent rxjs-spy from running completely, since I see output in the console, but it's still preventing the app from working.

I thought I could run rxjs-spy's tests with RxJS 7 to verify that the problem is with rxjs-spy. For that I've bumped TypeScript and RxJS dependency and have got at least four compilation errors, which I could not fix ad hoc.

Is v7 compatibility planned for rxjs-spy planned? If not, how are rxjs.tools coming along? :)

Please add package.json exports

With webpack 5, and importing rxjs-spy types via:

import { tag } from 'rxjs-spy/operators';

I get this error:

Webpack Compilation Error
Module not found: Error: Can't resolve 'rxjs-spy/operators' in (library path)
Did you mean 'index.js'?
BREAKING CHANGE: The request 'rxjs-spy/operators' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.

I get a similar issue if I use:

import { tag } from 'rxjs-spy/operators/tag';

And I can't use:

import { tag } from 'rxjs-spy';

because it isn't exported in the root package.

This is the only dependency where I'm seeing this issue. Other dependencies, eg rxjs, use package.json exports like:

// From rxjs package.json  :
  "sideEffects": false,
  "exports": {
    ".": {
      "node": "./dist/cjs/index.js",
      "es2015": "./dist/esm/index.js",
      "default": "./dist/esm5/index.js"
    },
    "./operators": {
      "node": "./dist/cjs/operators/index.js",
      "es2015": "./dist/esm/operators/index.js",
      "default": "./dist/esm5/operators/index.js"
    },
    ...

To workaround this issue, I've added to our webpack config:

  module: {
    rules: [
      {
        test: /[/\\]rxjs-spy[/\\].+\.m?js$/,
        resolve: {
          fullySpecified: false
        }
      },

Would it be possible to add package exports to this project?

ERROR TypeError: rxjs_1.of is not a function in an Electron Angular 5 application

Namaste!
I try to use your tool in an Electron Angular 5 application. I try to create the spy in the bootstrap file like this:

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { ApplicationModule } from 'modules/application/application.module';
import { environment } from 'environments';
import { create } from 'rxjs-spy';

if (environment.production) {
	enableProdMode();
}

create();

platformBrowserDynamic().bootstrapModule(ApplicationModule);

And I have this error in the console:

ERROR TypeError: rxjs_1.of is not a function
    at StackTracePlugin.beforeSubscribe (stack-trace-plugin.js:63)
    at spy-core.js:426
    at Array.forEach (<anonymous>)
    at notify_ (spy-core.js:304)
    at Observable.SpyCore.coreSubscribe_ [as subscribe] (spy-core.js:426)
    at subscribeToResult (subscribeToResult.js:67)
    at MergeMapSubscriber._innerSub (mergeMap.js:138)
    at MergeMapSubscriber._tryNext (mergeMap.js:135)
    at MergeMapSubscriber._next (mergeMap.js:118)
    at MergeMapSubscriber.Subscriber.next (Subscriber.js:92)

Seams like the problem happens when your tool registers plugins for Chromium Dev Tools.
What I do wrong? Can it be used in an Electron application at all?

rxjs-spy-devtools status

What is the status of rxjs-spy-devtools?
What usage was it originally intended to provide?
Is there any plan to continue development?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.