Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Strange error handling semantic. #12

Closed
sledorze opened this Issue · 19 comments

5 participants

@sledorze

a Promise should not behave differently when composed or not.
for instance; it should not throw an exception when rejected.

    var ooo = new Promise();
    ooo.reject(5);      // thorws!!!

(Remember; it's a monad; the error is a value).

@sledorze

Also a Promise is a value; binding before or after resolution should not change the semantic; otherwise the API is sensible to Async computation order; which it tries to abstract to ease reasonning about.

    var ooo = new Promise();
    ooo.reject(5);
    ooo.error(function (x) Node.console.info('should print $x')); // SHOULD PRINT :)
@jdonaldson
Owner

The short answer is that errors are not part of the semantics for handling values. I think this actually ends up being a feature, but I'm interested in hearing more about problems.

The error function is really there as a safety net for asynchronous operations. In all of your examples, it's trivial to handle those situations synchronously without using the error function or any other asynchronous code.

If you really must have an error function defined when you create the promise, you can do something like:

var ooo = new Promise(function(error) trace(error));
ooo.reject(5);
@sledorze
@jdonaldson
Owner

Please explain why this is so.

@sledorze

if I consume a service that expose Promises; and that there's an error; I want to be able to deal with it as in case of underlying error; I can't substitue it an alternative value.
Just think about how you would implement a timeout with the current API..

On a side note:
I've worked a lot with Futures / Promises / Async in general and the current behavior/semantic is not workable with.

You may check scala Futures, even if I don't always buy the dsl naming, the semantic is maintained.
http://docs.scala-lang.org/overviews/core/futures.html

Best :)

@jdonaldson
Owner

I'll look into it. Setting a timeout is one way, but it seems like a hack. The other way I could see working is by using a "start()" method that will kick off the promise evaluations, and make sure that error handlers are set. That adds more overhead though, so I'm more inclined to try a timeout approach first.

I'm still not seeing any of this as being a big limitation of promhx. The library is fully capable of managing errors, you just need to understand the mechanism.

@sledorze

fair enough

@labe-me

Just to tell that I felt the pain too :)

The main interest of futures/promises is to removes the burden of passing callbacks to method calls.

In the current implementation, to make things safe you have to create APIs like this:

class MyApi {
  public function doSomething(errorCb){
    var p = new promhx.Promise(errorCb);
    // ...
    return p;
  }
}

It forces the Api user to create an error handler before calling the API and preferably to pass the error handler through the entire Api calls.

Moreover I am not sure how well it integrates with the dO notation

// define the error callback before hand to be safe
function onError(err){
  // do something
}

promhx.mdo.PromiseM.dO({
    value <= doSomething(onError);
    other <= doOtherThing(onError);
})
.error(onError); // mmmm not sure it is a good idea

Regards
Laurent

@jdonaldson
Owner
@sledorze
@jdonaldson
Owner

There's a discussion on error handling buried in here:
promises-aplus/promises-spec#94

The main issue is that if you want synchronous error handling on the function inside of "then", you have to define the error handler along with the function argument:

p.then(handleValue, handleError);

This brings up a number of issues and questions. Can "then" work as a "map" function and enable do-notation? How does chaining proceed in the case of an error? E.g., if an error is handled with handleError, does the promise value resolve with its return value? Does it halt the chain? Must all "then" methods include an error handler? I'd like to think that there is a "right path", but you're going to find a lot of variation in implementation. Javascript alone has dozens of such libraries and specs right now.

Keep in mind that you can still manage errors with values in promhx. You can pass haxe.ds.Option types as a promise value, and keep your error values there. The "error" method is meant as a safety net for errors that come from stateful operations, and misc. other situations that aren't handled by a well specified error value. Since Haxe allows for OO and FP style, I think it's a good idea to include such a function.

@wighawag

what about another option: save the error until the "error" funciton is called ? (same as it does for value and the "then" function)

@jdonaldson
Owner
@jdonaldson
Owner

I've just pushed a rather large update that tries to address this error handling problem. It'll let you set error handlers after you've already set a then function, rejected a promise, etc. You can check out the test for it here.

It works pretty well for js and should be good for other runtimes with native event loops. But, it caused a lot of problems on other targets. I've rewritten test handlers for targets without event loops, and patched utest to make this sort of testing possible. I also had to disable php testing for the time being, it was giving me a mysterious runtime error.

@labe-me

It seems to work pretty well (except for a little thing but I will open a new issue).

@jdonaldson
Owner

sticking to this new error handling mechanism. Let me know if there's any new issues.

@jdonaldson jdonaldson closed this
@brendanjerwin

@jdonaldson I'm having some issues with the error behavior. Is this a reasonable place to discuss, or should I open a new issue?

@jdonaldson
Owner

Could you start a new thread? I did make changes to the error handling behavior, and I'd like the new thread to reflect the current state.

@brendanjerwin

Done. See #37

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.