question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Error handling and fromPromise()

See original GitHub issue

Let’s compare error handling in RxJS and Kefir:

RxJS. Example 1

import {Observable as O} from "rxjs"

O.from([1, 2, 3]).map(() => {
  return x.y
}).subscribe(
  (x) => console.log("x:", x),
  (e) => console.log("e:", e),
)
e: ReferenceError: x is not defined
    at MapSubscriber.project (/Users/ivankleshnin/Sandboxes/rxreact/ex1.rxjs.js:4:10)

Kefir. Example 1

import K from "kefir"

K.sequentially(100, [1, 2, 3]).map(() => {
  return x.y
}).observe(
  (x) => console.log("x:", x),
  (e) => console.log("e:", e),
)
ReferenceError: x is not defined
    at /Users/ivankleshnin/Sandboxes/rxreact/ex1.kefir.js:4:10

As we see, RxJS mixes operational and syntax errors which I consider a very bad idea. Both end up being handled in the same function. Kefir separates two error types. Only operational errors will be caught and handled by our custom (e) => ... lambda.

At least, both libraries show us the correct file, line and column. Now let’s take a look at Promise based streams:

RxJS. Example 2

import A from "axios"
import {Observable as O} from "rxjs"

O.fromPromise(A.get("http://localhost:8080/api/users/")).map(() => {
  return x.y
}).subscribe(
  (x) => console.log("x:", x),
  (e) => console.log("e:", e),
)
e: ReferenceError: x is not defined
    at MapSubscriber.project (/Users/ivankleshnin/Sandboxes/rxreact/ex2.rxjs.js:5:10)

The same behavior as in Example 1.

Kefir. Example 2

import A from "axios"
import K from "kefir"

K.fromPromise(A.get("http://localhost:8080/api/users/")).map(() => {
  return x.y
}).observe(
  (x) => console.log("x:", x),
  (e) => console.log("e:", e),
)
(node:4313) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): ReferenceError: x is not defined
(node:4313) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Now this one is broken. Kefir looses an error stack trace and the cause of our syntax error is lost. For some reason, the promise “sucked” the error in. It’s neither handled by error handler like in RxJS, nor escaped to the process like previously 😞 As a consequence, any promise-based stream in Kefir is a hell to debug right now.

I expected to get a process crash from sync errors in both Kefir examples.

Issue Analytics

  • State:open
  • Created 6 years ago
  • Comments:26 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
rpominovcommented, Dec 8, 2017

fromPromise and toPromise and that’s all?

Yep.

Maybe we should deprecate fromPromise / toPromise and at the same time create a separate repository that implements it using setImmediate polyfill?

We could even leave toPromise, but it will be weird to have toPromise but not fromPromise.

1reaction
mAAdhaTTahcommented, Dec 9, 2017

The issue with the current Promise interop is that this:

Kefir.fromPromise(Promise.resolve()).onValue(() => {throw new Error('test error');});

even throws an unhandledRejection error at all. It really shouldn’t; once you’re outside of “Promise land” (hur hur) because you converted to a Stream, errors should be in “Stream land” and behave according to Kefir’s semantics.

(using await someKefirStream.take(1).toPromise(); is an amazingly convenient thing in certain situations that ought to be recommended more so people know it’s an option)

I personally never use Kefir in that way; for me, if I’m using Observables, it’s Observables all the way down. I use fromPromise more often to interop with other libraries, especially fetch, so I’m disinclined to see value in it. If you use it a lot, or find it convenient, that might be an argument for leaving it.

Maybe we should just put some notes in its description about the issue and recommendations in this thread? (We could include a link to a fromPromise module that uses a setImmediate or an equivalent workaround.)

Is this to suggest that you’d want to leave the current behavior in the library and also add the second package suggested above?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Catching errors in Promise, Observable.fromPromise() and ...
Purpose of catch operator is to handle upstream errors and substitute desired value into observer::next (or re-throw if needed).
Read more >
Error handling with promises - The Modern JavaScript Tutorial
Promise chains are great at error handling. When a promise rejects, the control jumps to the closest rejection handler.
Read more >
Promise Error Handling - JavaScript Tutorial
Summary: in this tutorial, you will learn how to deal with error handling in promises. Suppose that you have a function called getUserById()...
Read more >
Promise.prototype.catch() - JavaScript - MDN Web Docs
The catch() method of a Promise object schedules a function to be ... The catch method is used for error handling in promise...
Read more >
RxJs Error Handling: Complete Practical Guide
The catchError Operator ... In synchronous programming, we have the option to wrap a block of code in a try clause, catch any...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found