Cancel Promise pattern (no cancellable promises)

Jan-Ivar Bruaroey jib at mozilla.com
Wed Jan 4 13:15:08 UTC 2017


Happy New Year!

Here's a cleanup iteration on this proposal: 
http://jsfiddle.net/jib1/wyq4sxsc/

You need Chrome or Firefox Developer Edition to run it due to async/await.

I've renamed the error to "CancelError" and made cancellation always 
fail with it, removing the "resumption" option.

PTAL!

Some comments on the earlier thread here:
  - The above fiddle suffers no accumulative "memory leak" problems. GC 
just works.
  - Synchronous inspection is necessary in multi-threaded cancellation 
only, not JS.

.: Jan-Ivar :.

On 10/26/16 10:41 PM, Jan-Ivar Bruaroey wrote:
> This is an alternative to cancellable promises that relies entirely on 
> existing JavaScript.
>
> I'm posting this here in hopes to bring the discussion back to 
> practical use cases and minimal needs.
>
> Example:
>
> Here's a setTimeout wrapper with cancellation, using a regular promise 
> as a cancellation token.
>
> let wait = (ms, cancel) => {
>   let id;
>   return Promise.race([
>     new Promise(resolve => id = setTimeout(resolve, ms)),
>     (cancel || new Promise(() => {})).then(() => clearTimeout(id))
>   ]);
> };
>
> function CancelledError() {
>   return Object.assign(new Error("The operation was cancelled."), 
> {name: "CancelledError"});
> }
>
> // Demo:
>
> async function foo() {
>   try {
>     let token = new Promise((r, e) => cancel.onclick = () => e(new 
> CancelledError()));
>     await wait(500);
>     console.log("Wait 4 seconds...");
>     await wait(4000, token);
>     console.log("Then wait 3 more seconds...");
>     await wait(3000, token);
>     console.log("Done.");
>   } catch (e) {
>     if (e.name != "CancelledError") throw e;
>     console.log("User cancelled");
>   }
> }
> foo();
>
>
> Here's the es6 version to run: http://jsfiddle.net/jib1/jz33qs32/
>
> Things to note:
> - Cancellation is targeted to specific operations (no "cancel chain" 
> ambition).
> - Token can be reused down the chain.
> - Cancellation is propagated using a regular (new) CancellationError 
> (no third rail).
> - It is up to the caller whether to treat cancellations as 
> non-exceptional.
> - Basic Promise.race pattern works even to wrap APIs that aren't 
> cancellable (stop waiting)
> - Pattern allows substituting any error (though I hope we standardize 
> CancelledError).
> - Pattern allows chain resumption by resolving token with any desired 
> value instead.
>
> I don't think this group needs to develop much here, maybe standardize 
> CancelledError, and have fetch() take a cancel promise argument like 
> wait() does in the example above.
>
> I'm open to hearing what use-cases are not be covered by this.
>
> Looking forward to your feedback. Thanks!
>
> .: Jan-Ivar :.
>


More information about the es-discuss mailing list