I can't think of any reason I've ever wanted to cancel a promise except maybe when uploading a file. Therefore I'm having a hard time grasping why this is such a big deal. What is another example?
* Server. Request handler starts expensive work. Let's say 4-5 database requests, some FS operations, rendering and sending response. Client disconnects. Running those operations will waste resources, we should stop. [1]
* Web. You can make at most 6 concurrent HTTP requests. They're precious resources. Dropping a request you no longer need will let others complete. It's nice to be able to abstract a painful ajax API behind something like a promise that doesn't lose the important ability to abort.
* React. View instance starts async fetch that eventually updates its state. User navigates to another view before it finishes. Updating the state after the component is unmounted is an error, and React will rightly complain. We should stop it.
* Server: abstracting an operation that's already cancelable behind a future. Let's say using Electron to render a website into a PDF. It's a really expensive operation, and the API is a pain to program against. You want to provide something as simple as a promise, but that doesn't lose the ability to stop it. [2]
[1] I write servers using Posterus coroutines, so all async code is automatically owned and canceled where appropriate: https://github.com/Mitranim/koa-ring
I actually had to write my way around non-cancellable promises quite a few times and my situation mirrors yours though mostly on the client:
I have a search page that updates results every time a new filter is updated (imagine you select a new tag to filter by, or narrow down the search somehow). This can be done faster than responses come back and can create a huge mess because some responses can come back faster than others.
This creates uncertainty in terms of what should be on the page. A few lines of code and it's fixed but the cool thing is that I get to throw away results that I don't care about and not process them (expensive-ish action).
This kind of situation happens somewhat often because a user can quickly navigate around, fire off a ton of requests and only really cares about the last one in the queue.
I haven't worked my way around it on a global scale which means that there could be a ton of requests being processed and thrown away right after for no good reason.
Glad you understand the problem. This is what futures are good for. Write an XMLHttpRequest adapter that returns a future, have an easy time composing or aborting operations.
Another example is for live search. As I type, each letter cancels pending search requests and starts a new one, making sure I don't show search results for a previous search term. I use this all the time.
Not good enough. Each ongoing request eats machine resources and counts towards the browser request limit (6 or so). Cancelation must release the underlying resources, which XMLHttpRequest allows you to do. By being promise-based, fetch is fundamentally broken. It's a dead-on-arrival tool.
I wouldn't be that harsh. even if it doesn't support cancellation today the support can be added later, eg through an optional CancellationToken parameter. This is eg how .Net Apis have added cancellation support. I would agree that cancellation would be good to have for lots of applications, but others will also be fine without it
Agreed, often it doesn't matter. Sometimes it DOES matter (high latency / low bandwidth / weak device), and then your program is slower than it could be. Why not pursue async primitives that let you manage resources properly at no downside?