- From: Tab Atkins Jr. <jackalmage@gmail.com>
- Date: Mon, 2 Mar 2015 15:06:57 -0800
- To: Dean Tribble <tribble@e-dean.com>
- Cc: "public-script-coord@w3.org" <public-script-coord@w3.org>, es-discuss <es-discuss@mozilla.org>
Thanks for this summary of some concerns! All valid, I think. In the GitHub issue <https://github.com/slightlyoff/ServiceWorker/issues/625>, there are some additional usability concerns, which I think make the cancellation token approach much less attractive, and lean the desired solution more towards a promise subclass. In particular: Cancellations should "chain" ====================== If you have a cancellable promise p1, and use .then() to produce a new promise p2, p2 should also be cancelable, and in the default case, should "chain up" to p1 and cause it to cancel as well. If you chain multiple promises off of p1, like p2a and p2b, then canceling either one of the p2X promises should do nothing, but cancelling *both* of them should cancel p1. In other words, p1 can ref-count its "child" promises that retain cancellation abilities, and cancel itself when everything consuming its result has been cancelled. This is important so you don't have to explicitly keep track of every single cancelable thing you're doing, if you're only using it to immediately chain onward again. You can just care about the final result, and if you end up not needing it, you can cancel it and it walks back and tries to cancel everything your result depends on. Combinators should combine cancellations ================================= If you do `let fp3 = FetchPromise.all(fp1, fp2)`, then an fp3.cancel() should try to cancel fp1 and fp2, as noted above. You want all the (cancellation-aware) combinators to be just as friendly as chaining directly, for usability. You need to be able to "clean" a cancellable promise ======================================== If the promise is what carries the cancellation ability, you need to be able to observe its value without carrying the cancellability around, to prevent spreading power around in an unwanted way (and prevent upping the "chained promises" refcount). This is doable by just wrapping it in a standard promise - `Promise.resolve(fetch(...))` will return a normal non-cancellable promise. A cancellation token is basically an ocap, and that means you have to keep track of the ocaps explicitly and separately from the promise for the result. This means more value-passing, and when you return another cancellable promise in the callback (like `fetch(...).then(x=>fetch(...))`), you have to explicitly smuggle that cancellation token out of the callback and hold onto both of them. Combinators become annoying, as you have to grab *all* of the cancel tokens used and hold them together, etc. Attaching cancellation to the promise just provides more usable behavior overall, without preventing safe behavior when you desire it. ~TJ
Received on Monday, 2 March 2015 23:07:45 UTC