{"action":"created","issue":{"url":"https://api.github.com/repos/whatwg/fetch/issues/27","labels_url":"https://api.github.com/repos/whatwg/fetch/issues/27/labels{/name}","comments_url":"https://api.github.com/repos/whatwg/fetch/issues/27/comments","events_url":"https://api.github.com/repos/whatwg/fetch/issues/27/events","html_url":"https://github.com/whatwg/fetch/issues/27","id":64476705,"number":27,"title":"Aborting a fetch","user":{"login":"annevk","id":1544111,"avatar_url":"https://avatars.githubusercontent.com/u/1544111?v=3","gravatar_id":"","url":"https://api.github.com/users/annevk","html_url":"https://github.com/annevk","followers_url":"https://api.github.com/users/annevk/followers","following_url":"https://api.github.com/users/annevk/following{/other_user}","gists_url":"https://api.github.com/users/annevk/gists{/gist_id}","starred_url":"https://api.github.com/users/annevk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/annevk/subscriptions","organizations_url":"https://api.github.com/users/annevk/orgs","repos_url":"https://api.github.com/users/annevk/repos","events_url":"https://api.github.com/users/annevk/events{/privacy}","received_events_url":"https://api.github.com/users/annevk/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":71,"created_at":"2015-03-26T09:08:23Z","updated_at":"2015-03-30T14:56:23Z","closed_at":null,"body":"## Goal\r\n\r\nProvide developers with a method to abort something initiated with `fetch()` in a way that is not overly complicated.\r\n\r\n## Previous discussion\r\n\r\n* https://github.com/whatwg/fetch/issues/20\r\n* https://github.com/slightlyoff/ServiceWorker/issues/592\r\n* https://github.com/slightlyoff/ServiceWorker/issues/625\r\n* https://github.com/whatwg/streams/issues/297\r\n\r\n## Viable solutions\r\n\r\nWe have two contenders. Either `fetch()` returns an object that is more than a promise going forward or `fetch()` is passed something, either an object or a callback that gets handed an object.\r\n\r\n### A promise-subclass\r\n\r\nIn order to not clash with cancelable promises (if they ever materialize) we should pick a somewhat unique method name for abortion. I think `terminate()` would fit that bill.\r\n\r\n    var f = fetch(url)\r\n    f.terminate()\r\n\r\nNote: the Twitter-sphere seemed somewhat confused about the capabilities of this method. It would most certainly terminate any ongoing stream activity as well. It's not limited to the \"lifetime\" of the promise.\r\n\r\n### A controller\r\n\r\nThe limited discussion on es-discuss https://esdiscuss.org/topic/cancelable-promises seemed to favor a controller. There are two flavors that keep coming back. Upfront construction:\r\n\r\n    var c = new FetchController\r\n    fetch(url, {controller: c})\r\n    c.abort()\r\n\r\nRevealing constructor pattern:\r\n\r\n    fetch(url, {controller: c => c.abort()})\r\n\r\n## Open issues\r\n\r\n* What is the effect on the promise? Both forever-pending and explicit rejection have reasonable arguments. We could offer the choice to the developer, but what should be the default?\r\n* What is the effect on the stream? I suspect the Streams Standard is already conclusive on this.\r\n* What syntax of the above two-three solutions do we favor?"},"comment":{"url":"https://api.github.com/repos/whatwg/fetch/issues/comments/87712056","html_url":"https://github.com/whatwg/fetch/issues/27#issuecomment-87712056","issue_url":"https://api.github.com/repos/whatwg/fetch/issues/27","id":87712056,"user":{"login":"getify","id":150330,"avatar_url":"https://avatars.githubusercontent.com/u/150330?v=3","gravatar_id":"","url":"https://api.github.com/users/getify","html_url":"https://github.com/getify","followers_url":"https://api.github.com/users/getify/followers","following_url":"https://api.github.com/users/getify/following{/other_user}","gists_url":"https://api.github.com/users/getify/gists{/gist_id}","starred_url":"https://api.github.com/users/getify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/getify/subscriptions","organizations_url":"https://api.github.com/users/getify/orgs","repos_url":"https://api.github.com/users/getify/repos","events_url":"https://api.github.com/users/getify/events{/privacy}","received_events_url":"https://api.github.com/users/getify/received_events","type":"User","site_admin":false},"created_at":"2015-03-30T14:56:23Z","updated_at":"2015-03-30T14:56:23Z","body":"> I don't even care much about fetch itself in terms of solution\r\n\r\nRight, but I think you missed my point, which is that `fetch(..)` and others have an explicit promise creation notion, so it's easier to see how the `ifCanceled` could be provided to the promise returned from `fetch(..)`, but there are other mechanisms like `async function` which implicitly create promises, and offer no such mechanism.\r\n\r\nThat's the major weakness of your idea, IMO, that it only works for explicit promise-creation tasks, but doesn't seem to work for implicit promise-creation tasks.\r\n\r\n> providing a canceling mechanism is the only way to go\r\n\r\nIf you're talking about canceling `fetch(..)` and `async function` and other promise-creating tasks, I agree. If you're talking about canceling the promise directly, rather than indirectly by virtue of the task being canceled, I don't agree. I don't think it follows at all that promises **have** to be cancelable to achieve the clearly agreed ideals that `fetch(..)` should be cancelable.\r\n\r\n>  if you always need boths whhy not just passing a promise with .cancel ability ?\r\n\r\nThat's precisely the point I've made many times in this thread, that you **don't always need** both, and in fact it's dangerous to system trustability to **always have both**. The advantage of the controller with separate observation and cancelability is that in places where you need both, you pass the controller, and in places where that's a bad idea, you pass only the promise (or only the cancelation)."}}