Open domenic opened 11 years ago
This works well, although it can be frustrating when you forget to add a .done()
. I think it could combine nicely with #2, which could even be modified so that we tracked missing .done()
handlers even if the promise wasn't rejected. That way #2 could help catch the cases where you forget to add .done()
Static analysis may also help catch missing .done()
s, especially if we had a foolproof way of determining that an object was a promise (like TypeScript!). I can't imagine trying to work out the edge cases there though.
hmm, but if any object that has a method .then
on it is treated as a promise, we know it's a promise if you ever call .then
on it, which should propagate through quite a long way with fairly minimal effort. Could be implemented as an extension to jshint
I'm strongly against requiring something like done
. I think it introduces extra cognitive load (I have to think about whether to use then
or done
), and refactoring hazards (forgetting to add or remove done
). Even though the refactoring hazard can be reduced a bit by always doing .then(f, r, p).done()
instead of .done(f, r, p)
, that doesn't completely remove the hazard. For example, you can't simply add/remove a return
anymore--you have to think about whether done
needs to be added/removed as well.
Also, it seems impossible to introduce done
in a debugging-only way. People simply will tend to sprinkle it through their code, and will not remove it, so any promise that doesn't support done
will break their code. That means that done
would need to be promoted to the same status as then
in order for anyone to use it in an interoperable way.
Personally, I'm much more interested in something like #2.
I think we need something to help support going back to node-style callbacks. Since done style callbacks crash on error, there needs to be a way of escaping promises.
It doesn't need to hit quite the level that .then
does, because unlike then it's easilly shimmed
The solution employed by Q and WinJS is a function called
done
on each promise, which is much likethen
except it signals that if there is an unhandled rejection for that promise, the program should crash. That is:Notably,
p.done(f, r)
is equivalent top.then(f, r).done()
, so you can choose either style as convenient; the latter is a bit nicer for refactoring, but the former signals intent nicely in other situations.Also,
done
returnsundefined
.The guidance is that when creating a promise (either directly or via
then
), you should always either (a)return
that promise so that the caller takes care of it, or (b) call.done()
on it.For more info on this see the MSDN article: http://msdn.microsoft.com/en-us/library/windows/apps/hh700337.aspx
Notably, this idea is composable with other ideas: if you "cap" a promise with
.done()
, that handles the rejection immediately with a sort of "default behavior" (i.e. crashing). So the other ideas can still be implementing to catch cases where you forget to cap.In other words, this idea reduces the number of unhandled rejections present in a program, and with inhuman programmer diligence brings that number down to zero. But in cases where that number is not brought down to zero, other ideas still apply.