clj-commons / manifold

A compatibility layer for event-driven abstractions
1.02k stars 106 forks source link

AssertionError not catched by manifold.deferred/catch #73

Closed martinklepsch closed 8 years ago

martinklepsch commented 8 years ago
(require '[manifold.deferred :as d])

(let [dd (d/deferred)]
  (-> dd
      (d/chain #(do (assert (string? %) "invalid") %) prn)
      (d/catch #(str "something unexpected:" (.getMessage %))))
  (d/success! dd nil))

Executing the above I expect one of the two outcomes:

  1. prn is called with the string value put onto the deferred
  2. the catch handler prints some exception

What happens instead is that true is returned, prn is not being called, no exception is printed.

I tried looking into the catch/catch' code but nothing stood out and AssertionError is extending Throwable so not sure what's going on there.

camdez commented 8 years ago

Hey, @martinklepsch. I think I can shed some light on this:

d/chain is creating a second deferred with a value derived from dd, but you're not retaining that new deferred in any way (and not forcing it to be delivered).

Compare with the following version:

(let [dd  (d/deferred)
      dd2 (-> dd
              (d/chain #(do (assert (string? %) "invalid") %) prn)
              (d/catch #(str "something unexpected:" (.getMessage %))))]
  (d/success! dd nil)
  [@dd @dd2])
;; => [nil "something unexpected:Assert failed: invalid\n(string? p1__81197#)"]

Hope that helps.

martinklepsch commented 8 years ago

@camdez oh — you're totally right. I expected something to be printed but str just makes a different return value which I'm not explicitly checking! Thanks!