Serious question - why is cancelling a promise a reasonable use case? Doesn't cancelling potentially invite non-deterministic state into your program? If not, what would be the difference from throwing?
The use case I heard was if for example the user clicks to load a view, which launches a background request, but then changes their mind and clicks to load a different view, which launches a different background request.
The user no longer cares about the original request. You could just discard the data when it arrives, but what if it's an expensive request for the client, or server, or both? You'd want a way to opt out of all that extra load on the system.
What's a good existing way to deal with this use-case? Is there a useful library that wraps setTimeout / other logic to determine the quality of a user's internet connection in case of very poor connectivity (2G etc) ?
The way to handle this case is to use Promise.race with 2 promises. The first promise is your logic. The second promise is rejected after a timeout. For more detail read the section "never calling the callback" from "you don't know js" book on "async" in chapter 3
https://github.com/getify/You-Dont-Know-JS/blob/master/async...
In react native, NetInfo has an api to detect network changes and I use that to stop all my setIntervals and start again with a different set of args, including wait time before calling again.
And yes, you can absolutely handle it by throwing an exception. But cancellation is such a common mechanism that you'd want to have 1) a standard exception type that can be used to indicate it, and that other async operations can handle in a composable fashion, and 2) a standard mechanism to request cancellation cooperatively, again, so that various layers can collaborate on handling a high-level cancellation request all the way to the lowest level like an I/O read.
A common case is for typeahead completion. You have a requst to the sever in flight to get typeaheads but the user has entered more characters and triggered another request. Now you would like to ignore the old one. Since async calls are not guaranteed to arrive in the same order they were sent, it would be nice to cancel the old one instead of maintaining logic to ignore it.