Open ForbesLindesay opened 11 years ago
I personally am not really in favour of this, but I think it would be preferable to #4 as we wouldn't see as many implementations break in the 'strict' mode
Actually I'm coming round to this idea. I don't think the 1 second idea is a good one, it introduces insanely non-deterministic behaviour.
We could add a .preserve()
method that essentially means "I promise I will handle exceptions later or it doesn't matter if this throws an exception". It would return this
rather than creating a new rejected promise.
The reason I think this is a plausible idea is that I think users rarely actually parse promises to the next turn of the event loop. Libraries do it all the time (e.g. all methods can be implemented as a reduce which then has this problem) but users rarely do it directly themselves.
I don't think that's feasible, sadly. preserve
would have to be implemented by everyone before libraries could use it, and in general I'm not sure "preserving" is any better than "capping" (with done
/end
).
The difference being, I guess, that mostly libraries would preserve, while mostly users will cap. While this seems like an attractive tradeoff at first, it fails from an interoperability standpoint. Users are precisely the ones who choose their promise implementation, while libraries have to be agnostic.
Yes, the only advantage I see is that beginner's use promise libraries, and experts write them (or at least that's how it should be), and at the moment beginner's are being stung by the poor error handling behaviour.
It should have been always fail fast from the day one. Now the spec is messed up and you guys trying to jump out of your pants to fix it. Throwing exceptions is a side effect, all side effects need to be handled explicitly which means if I mean to propagate a rejection I have a way to do it, it I want to crash I have a way to do it to. The spec ruled out the latter option leaving no choice made a side effect behaviour implicit. Ugh
I like the fail-fast approach the best. Fail-fast seems like the safest approach because you can write promises like this:
var promise = new Promise(function(resolve) {
kjjdjf(); // function that doesn't exist because I failed at typing
});
I feel like a syntax error like this should definitely result in an uncaught exception and preferably crash the program (or in browsers, log to console and send to onerror
). In async/Promise land, the behavior of an unhandled rejection should be the same as synchronous code. The whole point of Promises are to parallel synchronous code nicely.
I like the .preserve()
idea that @ForbesLindesay proposed... but it's not much different than just doing .catch(function nop(){})
on the Promise. You can always register a nop()
function on the Promise and ignore rejections... then sometime later when you actually want to handle the rejection, you can add another catch handler to the original Promise.
What if calling catch(cb)
returned a new Promise while calling catch()
with no callback argument behaved like the proposed .preserve()
and just returned this
Promise?
Fail fast all the time, but have a method to explicitly state that you intend to handle a rejection in a future turn of the event loop.
You could perhaps only throw if a rejection is not handled for say 1 second.