motorcyclejs / motorcycle

Open discussions for features/issues unrelated or general to current libraries.
15 stars 1 forks source link

Errors are silently ignored #24

Closed kimmobrunfeldt closed 7 years ago

kimmobrunfeldt commented 8 years ago

Hi,

I was wondering why my app didn't work and discovered that errors in my observable chain are caught somewhere and silently ignored. As a user there's no way I can catch those errors in a centralised way.

I created an example project where you can see what I mean: https://github.com/kimmobrunfeldt/motorcycle-errors-ignored

The main looks like this:

function main(sources) {
  var body$ = sources.HTTP
    .flatMap(x => x)
    .map(res => res)
    .tap(res => {
      console.log(res)
      // This error is not logged anywhere
      // It is caught somewhere in the most chain?
      throw new Error('test')
    })
    .startWith({});

  var request = {url: 'http://jsonplaceholder.typicode.com/posts/1'};
  return {
    DOM: body$.map(body => p(['body:', body])),
    HTTP: most.of(request).tap(a => console.log('Request url', a.url))
  };
}

Do you have idea how this could happen? This might be related to https://github.com/cujojs/most/issues/198

TylorS commented 8 years ago

Hello @kimmobrunfeldt

This is something I'm actually already working on addressing. You can check my progress here

kimmobrunfeldt commented 8 years ago

Ok sounds great!

kimmobrunfeldt commented 8 years ago

This seems to be a problem how I use the .flatMap in most.js, not with motorcycle itself.

When I edit my example like this, error is correctly logged:

function main(sources) {
  var body$ = sources.HTTP
    .flatMap(x => x)
+   .flatMapError(err => most.throwError(err))
    .map(res => res)
    .tap(res => {
      console.log(res)
      // This error is not logged anywhere
      // It is caught somewhere in the most chain?
      throw new Error('test')
    })
    .startWith({});

  var request = {url: 'http://jsonplaceholder.typicode.com/posts/1'};
  return {
    DOM: body$.map(body => p(['body:', body])),
    HTTP: most.of(request).tap(a => console.log('Request url', a.url))
  };
}
kimmobrunfeldt commented 8 years ago

I tried to reproduce this behavior with only most.js but couldn't do it. E.g. this test script:

var most = require('most');

function* integers() {
  yield 1;
  yield 2;
  yield new Error('error inside generator');
  return yield 3;
}

var stream$$ = most.of(most.from(integers()));
var stream$ = stream$$.flatMap(x => x);

stream$.observe(i => {
  console.log(i);
});

logs the errors correctly. So I'm not sure if this is happening because of what motorcycle/http driver is doing.

TylorS commented 8 years ago

I'm not totally sure. Maybe @briancavalier could way in on the most.js stuff

briancavalier commented 8 years ago

What version of most.js are you using, @kimmobrunfeldt? And did you use the same version in your app and in the simplified test above (the one with the generator)? On the same VM?

most.js propagates errors through the promise returned from observe/drain/reduce. As of 0.18.0, most.js uses native Promise. That means that if you're on a platform that has unhandled promise rejection reporting (newer versions of chrome and FF report unhandled promise rejections when promises are garbage collected. I believe node does as well, since it's v8, but not sure how reliable it is), unhandled errors will be reported. You can also use a promise shim that has good unhandled rejection reporting support, like creed, when, or bluebird.

I'm not sure that's the issue, but figured it might be worth checking. If you can create a simple reproducible test case, I'll be happy to dig into it!