- From: Jake Archibald <notifications@github.com>
- Date: Tue, 14 Apr 2015 08:57:38 -0700
- To: whatwg/fetch <fetch@noreply.github.com>
- Message-ID: <whatwg/fetch/issues/27/92929061@github.com>
We're currently looking into two solutions: Cancellable tokens and cancellable promises. I'm going by the following requirements: * Promises should have `.finally(func)`, along with `.then(onfullfill, onreject, onfinally)` to mirror the sync counterpart * If a promise has settled before cancellation, cancellation is a no-op * A cancelled promise will not call `onfullfill` or `onreject`, but will call `onfinally` * Cancellation should ideally be chain aware (having to manually pass a token to each call isn't a great API) * If cancellation happens after a promise has started work, but hasn't yet resolved, it should be able to react to this via a callback that can easily cancel the underlying operation(s) * A parent promise should be able to react if all its children have cancelled * It should be easy for a promise receiver to signal disinterest/cancellation (such as `event.respondWith` in a service worker) * It should be easy to vend a promise that cannot be cancelled by the receiver Have I missed anything? I'm still a fan of the ref-counting approach, but it creates a tricky situation and I'm open to suggestions… Take the following nonsensical example: ```js var fetchPromise = fetch(url); var jsonPromise = fetchPromise.then(r => r.json()); var fetchPromise2 = fetch(url2); var waitingPromise = fetchPromise2.then(_ => fetchPromise); // Ref counts // fetchPromise: 2 // jsonPromise: 0 // waitingPromise: 0 ``` Imagine `fetchPromise` has yet to settle, `fetchPromise2` has fulfilled with a `Response`, `waitingPromise` has resolved with `fetchPromise`. Then: ```js waitingPromise.cancel(); ``` 1. `waitingPromise` cannot be marked for cancelation as it has resolved. But since it hasn't settled, its resolved value, `fetchPromise` has its ref count decreased by 1, to 1. And there's the problem. Although `.cancel` was called on this unsettled promise, it continues to resolve with `fetchPromise`. This wouldn't be a problem with: ```js var fetchPromise = fetch(url); var jsonPromise = fetchPromise.then(r.clone() => r.json()); var fetchPromise2 = fetch(url2); var waitingPromise = fetchPromise2.then(_ => fetchPromise).then(); // Ref counts // fetchPromise: 2 // jsonPromise: 0 // waitingPromise: 0 ``` …as `waitingPromise` hasn't resolved due to the added `.then()`. I think we either need to find a way to do something like that in the spec (maybe it does already?), or allow a resolved but unsettled promise to cancel. Both of these would also help if a `CancelablePromise` resolved with a foreign thenable. --- Reply to this email directly or view it on GitHub: https://github.com/whatwg/fetch/issues/27#issuecomment-92929061
Received on Tuesday, 14 April 2015 15:58:16 UTC