Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug][hdom, rstream] error is silently ignored #125

Open
nkint opened this issue Sep 4, 2019 · 3 comments
Open

[Bug][hdom, rstream] error is silently ignored #125

nkint opened this issue Sep 4, 2019 · 3 comments

Comments

@nkint
Copy link
Contributor

nkint commented Sep 4, 2019

Hi!
I don't actually know which combination of hdom, rstream and generators causes this issue but in this particular case if I have some error it is not shown and it vanishes into the void causing troubleshooting and debugging quite difficult.

I'll try to investigate on it but maybe someone has a smart enlightenment.

import { stream, sync } from '@thi.ng/rstream'
import { updateDOM } from '@thi.ng/transducers-hdom'
import { map, scan, count, range } from '@thi.ng/transducers'

function getColor(n: number, clicks: number) {
  if (n === 3) {
    throw new Error('dudee')
  }
  return n === clicks - 1 ? 'red' : 'black'
}

const app = ({ clicks }: any) => [
  'div',
  [
    'a',
    {
      href: '#',
      onclick: () => clickStream.next(0),
    },
    `${clicks} clicks`,
  ],
  ...[...range(clicks)].map(n => {
    console.log(n, clicks - 1)
    return ['p', { style: { color: getColor(n, clicks) } }, n]
  }),
]

const clickStream = stream().transform(scan(count(-1)))
clickStream.next(0)

sync<any, any>({
  src: {
    clicks: clickStream,
  },
}).transform(map(app), updateDOM({ root: document.body }))
@nkint nkint changed the title error is silently ignored [Bug][hdom, rstream] error is silently ignored Sep 4, 2019
@postspectacular
Copy link
Member

postspectacular commented Sep 4, 2019

Ciao, @nkint - am back from the mountains... will look into this tomorrow, but 2 things:

  1. currently there's no explicit error handling (yet!) for transform()ers (transducers) - this will be added as part of the ongoing updates on the feature/rstream-opts branch
  2. you can enable error logging like this:
import { ConsoleLogger, LogLevel } from "@thi.ng/api";
import { setLogger } from "@thi.ng/rstream";

// set package specific logger instance
setLogger(new ConsoleLogger("rstream", LogLevel.WARN));

Be aware that not all errors will be caught & logged via this mechanism, but it should work for the above use case...

In general, each ISubscriber can provide an error hook, but transducers added via transform() are handled differently, and as mentioned, currently still lack user controllable error handling/hooks...

@postspectacular
Copy link
Member

@nkint Just to add to this, here's how you can add/override an error handler for a transform() subscription (based on your example)

const main = sync<any, any>({
    src: {
        clicks: clickStream
    }
});
const sub = main.transform(map(app), updateDOM({ root: document.body }));
sub.error = (e) => alert(e.message);

@postspectacular
Copy link
Member

postspectacular commented Sep 5, 2019

The other thing worth noting here is that iff a custom error handler is provided, the subscription will NOT automatically go into the ERROR state and can receive future values. Only if the default error handler is called, the sub switches to that state and silently ignores further inputs... This behavior still needs to be documented. But the underlying reasoning for this is that you could do something like:

import { fromIterable, stream, sync } from "@thi.ng/rstream";
import { map, range, sideEffect } from "@thi.ng/transducers";
import { updateDOM } from "@thi.ng/transducers-hdom";

const app = ({ mainXform, error }: any) => [
    "div",
    ["h1", mainXform],
    error && ["div.red", "error: ", error]
];

const main = fromIterable(range(5), 1000);

const error = stream<string | null>();
error.next(null);

const mainXform = main.transform(
    sideEffect((x: number) => {
        if (x > 2) throw new Error(String(x));
    }),
    map((x: number) => x * 10)
);
mainXform.error = (e: Error) => error.next(e.message);

sync<any, any>({
    src: { mainXform, error }
}).transform(map(app), updateDOM());

postspectacular added a commit that referenced this issue Mar 4, 2021
- update Subscription.error() and ensure error is at least written to
  console, even if the default `NULL_LOGGER` is used
- addresses #125, #276
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants