Re: [fetch] Aborting a fetch (#27)

After I made this I started thinking about that as well. Consider:
```js
function load(url){
  let a = fetch(url);
  let c = a.then(b);
  let e = c.then(d);

  setTimeout(() => c.cancel(), 100);

  return e;
}
```

In the above example the middle of the chain is cancelled/ignored/aborted, and the message that work should be stopped, that the result is no longer needed and that things should be cleaned up will travel in two different directions; up from `c` to either `a` or `b`, depending on if `a` has resolve yet, and down from `c` to `e` and beyond, to let them know that there wont be any value and that the promises should clean up so as many of the promises as possible can be garbage collected.

If a signal should be sent down the chain that it has been cancelled, then I don't think that it is the original promise (the top of the chain, either `a` or `b` in the code above) that should provide this value, since they don't know why it was cancelled. If a value is to be provided then it is the canceller that should provide this value. 

The canceller is further down the chain, and the value it provides will travel down the chain, and so there is no need to send this value up the chain. That is, neither `a` nor `b` need to know why they have been cancelled. It might be that the promises down the chain want to know why, and so this value should travel down to `e`. `d` doesn't exist yet, so it doesn't need to be cancelled.

One option then is to have `cancel()`/`ignore()`/`abort()` be called with an optional parameter and have the promise resolve to that value instead of being forever pending. We could also let it be called with a function that either returns a value or throws an error, and have it fulfil in the first case and reject in the second case. But this introduces a way to inject a value into a promise chain at any point, even after it has resolved, which I don't think is a good idea at all! Then the method shouldn't be called `cancel()` but `resolve()`/`reject()`, and it makes cancellable promises something completely different than normal promises.

This can also be implemented using nested chains:

```js
let e = ((url, cancel) => {
  let a = fetch(url);
  let c = a.then(b);
  return Promise.race([c, cancel]);
})(url, cancel);
let e = c.then(d);
```

The only remaining option is to have a third possibility for the promise `then` method; `onCancelled`:
```js
somePromise.then(onResolved, onRejected, onCancelled);
```

Again, if a value should be passed down the chain to this onCancelled method, then I think that should be from the canceller, not from the cancelled promise. But this introduces complexity in whether or not this method behaves like the two other, ie can you `return` and `throw` in it and what happens if you return a promise? 

---
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/fetch/issues/27#issuecomment-90927239

Received on Wednesday, 8 April 2015 14:06:34 UTC